Convert 4 bytes char to int32 in C
Solution 1
Reverse the order of the a[] indexes, e.g,. a[0] -> a[3]
I think you have the endianness in reverse.
Try this:
a[3] = (num>>24) & 0xFF;
a[2] = (num>>16) & 0xFF;
a[1] = (num>>8) & 0xFF;
a[0] = num & 0xFF;
Solution 2
To see what happens use
printf("%x\n", ...);
to print both input and output number.
Endian-independent way:
x = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3];
Solution 3
This line is never going to work correctly on a little-endian machine:
x = *(int *)a;
You need to unpack the data before you print out the value.
Solution 4
Your code a[0] = (num>>24) & 0xFF;
takes the most significant 8 bits from num
and sticks them in the first byte of a
. On little endian machines the first byte holds the least signficant bits. That means that on little endian machines, this code takes the most significant 8 bits and stores them in the place where the least significant bits go, changing the value.
2130706432 is 0x7F000000 in hex, and 127 is 0x0000007F.
Also, x = *(int *)a;
results in undefined behavior. Consider hardware where reading an int from an improperly aligned address causes a bus error. If a
doesn't happen to be aligned properly for an int then the program would crash.
A correct approach to interpreting the bytes as an int
would be std::memcpy(&x, a, sizeof x);
stackunderflow
Updated on July 09, 2022Comments
-
stackunderflow almost 2 years
I first convert an int32 number to char[4] array, then convert the array back to int32 by (int *), but the number isn't the same as before:
unsigned int num = 2130706432; unsigned int x; unsigned char a[4]; a[0] = (num>>24) & 0xFF; a[1] = (num>>16) & 0xFF; a[2] = (num>>8) & 0xFF; a[3] = num & 0xFF; x = *(int *)a; printf("%d\n", x);
the output is 127. And if I set num = 127, the output is 2130706432. Does anyone have ideas?
-
ninjalj over 12 yearsAdditionally, it may not work on big-endian machines with compilers that take advantage of strict-aliasing rules.
-
rightaway717 over 9 yearsI don't know why this is voted up. As if it's an endian-independent way, it should work on my PC too. But I have to do quite the opposite
uint32_t var2 = (v[3] << 24) | (v[2] << 16) | (v[1] << 8) | v[0];
-
rightaway717 over 9 yearsI use
vector<unsigned char>
and fill it withuint32_t
vars usingmemcpy
:memcpy(&v[0], &var, sizeof var);
-
Adam Trhon over 9 years@rightaway717 So save it in endianess of your computer. To do it endian-independent way you have to convert uint32_t -> array as OP does and array -> uint32_t as I do.