I have the following simple program that uses a union to convert between a 64 bit integer and its corresponding byte array:
union u
{
uint64_t ui;
char c[sizeof(uint64_t)];
};
int main(int argc, char *argv[])
{
u test;
test.ui = 0x0123456789abcdefLL;
for(unsigned int idx = 0; idx < sizeof(uint64_t); idx++)
{
cout << "test.c[" << idx << "] = 0x" << hex << +test.c[idx] << endl;
}
return 0;
}
What I would expect as output is:
test.c[0] = 0xef
test.c[1] = 0xcd
test.c[2] = 0xab
test.c[3] = 0x89
test.c[4] = 0x67
test.c[5] = 0x45
test.c[6] = 0x23
test.c[7] = 0x1
But what I actually get is:
test.c[0] = 0xffffffef
test.c[1] = 0xffffffcd
test.c[2] = 0xffffffab
test.c[3] = 0xffffff89
test.c[4] = 0x67
test.c[5] = 0x45
test.c[6] = 0x23
test.c[7] = 0x1
I'm seeing this on Ubuntu LTS 14.04 with GCC.
I've been trying to get my head around this for some time now. Why are the first 4 elements of the char array displayed as 32 bit integers, with 0xffffff prepended to them? And why only the first 4, why not all of them?
Interestingly enough, when I use the array to write to a stream (which was the original purpose of the whole thing), the correct values are written. But comparing the array char by char obviously leads to problems, since the first 4 chars are not equal 0xef, 0xcd, and so on.
Using char
is not the right thing to do since it could be signed
or unsigned
. Use unsigned char
.
union u
{
uint64_t ui;
unsigned char c[sizeof(uint64_t)];
};
char
gets promoted to an int
because of the prepended unary +
operator. . Since your chars
are signed
, any element with the highest by set to 1
is interpreted as a negative number and promoted to an integer with the same negative value. There are a few different ways to solve this:
+
: ... << test.c[idx] << ...
. This may print the char as a character rather than a number, so is probably not a good solution.c
as unsigned char
. This will promote it to an unsigned int
.+test.c[idx]
before it is passed: ... << (unsigned char)(+test.c[idx]) << ...
&
: ... << +test.c[idx] & 0xFF << ...
. This will only display the lowest-order byte no matter how the char
is promoted.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With