I have a library driven result stored as an int16_t value (and it is a negative, which I can use the absolute value of) and another library function that requires this value a few steps later in the form uin8_t*. How can this be done without using String?
The following code works, but uses dreaded Strings. Is there a way to do this without invoking String or std::string?
void setup() {
Serial.begin(9600);
}
void loop() {
delay(5000);
String initialVal= String(-fetchInt());
Serial.print("Initial value is: ");Serial.println(initialVal);//prints "76"
uint8_t medianVal[sizeof(initialVal);
medianVal.getBytes(medianVal, sizeof(initialVal));
Serial.print("median value is: ");Serial.println(medianVal);//prints "76"
uint8_t* finalVal = medianVal;
Serial.print("final value is: ");Serial.println((char*)finalVal);//prints "76"
}
int16_t fetchInt(){
return -76;
}
So, how can I turn int16_t into uint8_t*?
It has been pointed out in comments below that
Serial.println(static_cast<unsigned>(*finalVal)); works, but this solution converts the uint8_t to an unsigned int and the method requires uint8_t*.
I come from Java and the like and it seems crazy that it is so hard to convert an integer to a string.
A pointer of type uint8_t cannot point to an object of type int16_t; you need to copy the value of firstVal, but therefore you'll need a separate object to take on the value.
uint8_t firstValAbs = firstVal >= 0 ? firstVal : -firstVal;
uint8_t* secondVal = &firstValAbs;
Note: uint8_t x = -34 will not give you the absolute value of -34, i.e. it will not result in 34. You'll rather get a two's complement of -34, i.e. 255-34+1 == 222.
int16_t stores a signed numeric value using 16 bits (-32,768 to 32,767).
uint8_t stores an unsigned numeric value using 8 bits (0 to 255).
If you are sure your int16_t value fits into an uint8_t after changing the sign, you can just assign it:
int16_t firstVal = -76;
uint8_t secondVal = -firstVal;
Now, if you need a pointer to the second value, you can just create it. You can not point directly to firstVal because you need to store the changed value.
uint8_t* secondValPointer = &secondVal;
This uint8_t* may be interpreted as a pointer to a character in your library. Normally, you should use char for this purpose (also 8 bits, but it is implementation defined if it is signed or unsigned). You can cast this pointer to char*, although you need to tell the compiler you want to cast between pointers using reinterpret_cast:
char *secondValAsChar = reinterpret_cast<char*>(secondValPointer);
Now, you can treat this pointer as a pointer to character. For example the following code will print 'L' because ASCII code for L is 76:
std::cout << *secondValAsChar << std::endl;
However, you must be very careful with this pointer because secondValAsChar is not a null terminated string, so you may not use the old common methods like strcat.
Related
I have and array of hexa values called
const char receiptLogo[] = {0x01,0x80,0x00,0xB4};
When I tried to get the value Rprintf("%x\r\n",receiptLogo[3]);
Value was displayed as "ffffffb4" and sometimes it was displayed as "b4"
The whole Function is as
void PRINT_PrintLogo( const char Data[])
{
unsigned int height=0;
const char receiptLogo[] = {0x01,0x80,0x00,0xB4};
height=(((unsigned short)receiptLogo[2] ) << 8) | ((unsigned short)receiptLogo[3] );
Rprintf("height=%d,%x,%x\r\n",height,Data[2],Data[3]);
}
The output of this function is
height=65460,0,ffffffb4
although in other times the output is height=180,0,b4
Kindly please advise the reason behind it
in printf() the %X format specifier is hexadecimal int. If you pass a char as a parameter and the most significant bit is set it should sign extend to fill the size of an integer. The compiler may optimize by packing variables and sometimes your variable my be in different places with respect to byte boundaries (i.e. the char may end up in the least significant byte or most significant byte of a 32-bit integer). This access may cause this behavior.
How do I assign value to uint32_t key[4]
I initially have this uint32_t iv[2] = {0xFFFFFFDD};
Then at my 2nd run.. I need assign a new value.. lets assume the new value is
10273348653513887325 (decimal) but recorded as string for now.
string value = "10273348653513887325";
But I want change the value of iv from 0xFFFFFFDD (hexadecimal) to 10273348653513887325 (decimal)
How do I do it?
You don't. 10273348653513887325 as a decimal will not fit into a uint32_t. You can pretend that iv is a 64 bit value thus:
uint64_t* piv = (uint64_t*)&iv[0];
*piv = decValue; // where dec value is the decimal conversion of the string
but after you've done that, what you'll really have are two 32 bit values that each have a portion of the value you're trying to store. Just because that's not awkward enough, the endianness of the architecture you're using comes into play. So don't do that.
Another alternative is to use an anonymous union of 2 32bit values and one 64 bit value.
It might merit pointing out that the assignment
uint32_t iv[2] = {0xFFFFFFDD };
results in the first element in iv having that value, and the second containing 0. Is that what you meant?
As pointed out by #hvd, there's some lack of clarity about what you're trying to achieve.
What is the use of unsigned char pointers? I have seen it at many places that pointer is type cast to pointer to unsinged char Why do we do so?
We receive a pointer to int and then type cast it to unsigned char*. But if we try to print element in that array using cout it does not print anything. why? I do not understand. I am new to c++.
EDIT Sample Code Below
int Stash::add(void* element)
{
if(next >= quantity)
// Enough space left?
inflate(increment);
// Copy element into storage, starting at next empty space:
int startBytes = next * size;
unsigned char* e = (unsigned char*)element;
for(int i = 0; i < size; i++)
storage[startBytes + i] = e[i];
next++;
return(next - 1); // Index number
}
You are actually looking for pointer arithmetic:
unsigned char* bytes = (unsigned char*)ptr;
for(int i = 0; i < size; i++)
// work with bytes[i]
In this example, bytes[i] is equal to *(bytes + i) and it is used to access the memory on the address: bytes + (i* sizeof(*bytes)). In other words: If you have int* intPtr and you try to access intPtr[1], you are actually accessing the integer stored at bytes: 4 to 7:
0 1 2 3
4 5 6 7 <--
The size of type your pointer points to affects where it points after it is incremented / decremented. So if you want to iterate your data byte by byte, you need to have a pointer to type of size 1 byte (that's why unsigned char*).
unsigned char is usually used for holding binary data where 0 is valid value and still part of your data. While working with "naked" unsigned char* you'll probably have to hold the length of your buffer.
char is usually used for holding characters representing string and 0 is equal to '\0' (terminating character). If your buffer of characters is always terminated with '\0', you don't need to know it's length because terminating character exactly specifies the end of your data.
Note that in both of these cases it's better to use some object that hides the internal representation of your data and will take care of memory management for you (see RAII idiom). So it's much better idea to use either std::vector<unsigned char> (for binary data) or std::string (for string).
In C, unsigned char is the only type guaranteed to have no trapping values, and which guarantees copying will result in an exact bitwise image. (C++ extends this guarantee to char as well.) For this reason, it is traditionally used for "raw memory" (e.g. the semantics of memcpy are defined in terms of unsigned char).
In addition, unsigned integral types in general are used when bitwise operations (&, |, >> etc.) are going to be used. unsigned char is the smallest unsigned integral type, and may be used when manipulating arrays of small values on which bitwise operations are used. Occasionally, it's also used because one needs the modulo behavior in case of overflow, although this is more frequent with larger types (e.g. when calculating a hash value). Both of these reasons apply to unsigned types in general; unsigned char will normally only be used for them when there is a need to reduce memory use.
The unsinged char type is usually used as a representation of a single byte of binary data. Thus, and array is often used as a binary data buffer, where each element is a singe byte.
The unsigned char* construct will be a pointer to the binary data buffer (or its 1st element).
I am not 100% sure what does c++ standard precisely says about size of unsigned char, whether it is fixed to be 8 bit or not. Usually it is. I will try to find and post it.
After seeing your code
When you use something like void* input as a parameter of a function, you deliberately strip down information about inputs original type. This is very strong suggestion that the input will be treated in very general manner. I.e. as a arbitrary string of bytes. int* input on the other hand would suggest it will be treated as a "string" of singed integers.
void* is mostly used in cases when input gets encoded, or treated bit/byte wise for whatever reason, since you cannot draw conclusions about its contents.
Then In your function you seem to want to treat the input as a string of bytes. But to operate on objects, e.g. performing operator= (assignment) the compiler needs to know what to do. Since you declare input as void* assignment such as *input = something would have no sense because *input is of void type. To make compiler to treat input elements as the "smallest raw memory pieces" you cast it to the appropriate type which is unsigned int.
The cout probably did not work because of wrong or unintended type conversion. char* is considered a null terminated string and it is easy to confuse singed and unsigned versionin code. If you pass unsinged char* to ostream::operator<< as a char* it will treat and expect the byte input as normal ASCII characters, where 0 is meant to be end of string not an integer value of 0. When you want to print contents of memory it is best to explicitly cast pointers.
Also note that to print memory contents of a buffer you would need to use a loop, since other wise the printing function would not know when to stop.
Unsigned char pointers are useful when you want to access the data byte by byte. For example, a function that copies data from one area to another could need this:
void memcpy (unsigned char* dest, unsigned char* source, unsigned count)
{
for (unsigned i = 0; i < count; i++)
dest[i] = source[i];
}
It also has to do with the fact that the byte is the smallest addressable unit of memory. If you want to read anything smaller than a byte from memory, you need to get the byte that contains that information, and then select the information using bit operations.
You could very well copy the data in the above function using a int pointer, but that would copy chunks of 4 bytes, which may not be the correct behavior in some situations.
Why nothing appears on the screen when you try to use cout, the most likely explanation is that the data starts with a zero character, which in C++ marks the end of a string of characters.
I'm working on an embedded platform (ARM) and have to be careful when dealing with bit patterns. Let's pretend this line is beyond my influence:
uint8_t foo = 0xCE; // 0b11001110
Interpreted as unsigned this would be 206. But actually it's signed, thus resembling -50. How can I continue using this value as signed?
int8_t bar = foo; // doesn't work
neither do (resulting in 0x10 or 0x00 for all input values)
int8_t bar = static_cast<int8_t>(foo);
int8_t bar = reinterpret_cast<int8_t&>(foo);
I just want the bits to remain untouched, ie. (bar == 0xCE)
Vice versa I'd be interested how to get bit-patters, representing negative numbers, into unsigned variables without messing the bit-pattern. I'm using GCC.
The following works fine for me, as it should though as the comments say, this is implementation-defined:
int x = (signed char)(foo);
In C++, you can also say:
int x = static_cast<signed char>(foo);
Note that promotion always tries to preserve the value before reinterpreting bit patterns. Thus you first have to cast to the signed type of the same size as your unsigned type to force the signed reinterpretation.
(I usually face the opposite problem when trying to print chars as pairs of hex digits.)
uint8_t foo = 0xCE; // 0b11001110
int8_t bar;
memcpy( &bar, &foo, 1 );
It even has the added bonus that 99% of compilers will completely optimise out the call to memcpy ...
Something ugly along the lines of this?
int8_t bar = (foo > 127) ? ((int)foo - 256) : foo;
Doesn't rely on a conversion whose behaviour is undefined.
With GCC chances are that unsigned values are two's complement, even on your embedded platform.
Then the 8-bit number 0xCE represents 0xCE-256.
Because two's complement is really just modulo 2n, where n is the number of bits in the representation.
EDIT: hm, for rep's sake I'd better give a concrete example:
int8_t toInt8( uint8_t x )
{
return (x >= 128? x - 256 : x);
}
EDIT 2: I didn't see the final question about how to get a bit pattern into an unsigned variable. That's extremely easy: just assign. The result is guaranteed by the C++ standard, namely that the value stored is congruent (on-the-clock-face equal) to the value assigned, modulo 2n.
Cheers & hth.,
You can access the representation of a value using a pointer. By reinterpreting the pointer type, not the value type, you should be able to replicate the representation.
uint8_t foo = 0xCE;
int8_t bar = *reinterpret_cast<int8_t*>(&foo);
Is it safe to convert, say, from an unsigned char * to a signed char * (or just a char *?
The access is well-defined, you are allowed to access an object through a pointer to signed or unsigned type corresponding to the dynamic type of the object (3.10/15).
Additionally, signed char is guaranteed not to have any trap values and as such you can safely read through the signed char pointer no matter what the value of the original unsigned char object was.
You can, of course, expect that the values you read through one pointer will be different from the values you read through the other one.
Edit: regarding sellibitze's comment, this is what 3.9.1/1 says.
A char, a signed char, and an unsigned char occupy the same amount of storage and have the same alignment requirements (3.9); that is, they have the same object representation. For character types, all bits of the object representation participate in the value representation. For unsigned character types, all possible bit patterns of the value representation represent numbers.
So indeed it seems that signed char may have trap values. Nice catch!
The conversion should be safe, as all you're doing is converting from one type of character to another, which should have the same size. Just be aware of what sort of data your code is expecting when you dereference the pointer, as the numeric ranges of the two data types are different. (i.e. if your number pointed by the pointer was originally positive as unsigned, it might become a negative number once the pointer is converted to a signed char* and you dereference it.)
Casting changes the type, but does not affect the bit representation. Casting from unsigned char to signed char does not change the value at all, but it affects the meaning of the value.
Here is an example:
#include <stdio.h>
int main(int args, char** argv) {
/* example 1 */
unsigned char a_unsigned_char = 192;
signed char b_signed_char = b_unsigned_char;
printf("%d, %d\n", a_signed_char, a_unsigned_char); //192, -64
/* example 2 */
unsigned char b_unsigned_char = 32;
signed char a_signed_char = a_unsigned_char;
printf("%d, %d\n", b_signed_char, b_unsigned_char); //32, 32
return 0;
}
In the first example, you have an unsigned char with value 192, or 110000000 in binary. After the cast to signed char, the value is still 110000000, but that happens to be the 2s-complement representation of -64. Signed values are stored in 2s-complement representation.
In the second example, our unsigned initial value (32) is less than 128, so it seems unaffected by the cast. The binary representation is 00100000, which is still 32 in 2s-complement representation.
To "safely" cast from unsigned char to signed char, ensure the value is less than 128.
It depends on how you are going to use the pointer. You are just converting the pointer type.
You can safely convert an unsigned char* to a char * as the function you are calling will be expecting the behavior from a char pointer, but, if your char value goes over 127 then you will get a result that will not be what you expected, so just make certain that what you have in your unsigned array is valid for a signed array.
I've seen it go wrong in a few ways, converting to a signed char from an unsigned char.
One, if you're using it as an index to an array, that index could go negative.
Secondly, if inputted to a switch statement, it may result in a negative input which often is something the switch isn't expecting.
Third, it has different behavior on an arithmetic right shift
int x = ...;
char c = 128
unsigned char u = 128
c >> x;
has a different result than
u >> x;
Because the former is sign-extended and the latter isn't.
Fourth, a signed character causes underflow at a different point than an unsigned character.
So a common overflow check,
(c + x > c)
could return a different result than
(u + x > u)
Safe if you are dealing with only ASCII data.
I'm astonished it hasn't been mentioned yet: Boost numeric cast should do the trick - but only for the data of course.
Pointers are always pointers. By casting them to a different type, you only change the way the compiler interprets the data pointed to.