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. 当char value > 0x7f
转换为int时,使用unsigned char或使用test.c[idx] & 0xff
来避免符号扩展。
它是unsigned char vs signed char并且它转换为整数
The unary plus causes the char
to be promoted to a int
(integral promotion). Because you have signed chars the value will be used as such and the other bytes will reflect that.
It is not true that only the four are ints, they all are. You just don't see it from the representtion since the leading zeroes are not shown.
Either use unsigned char
s or & 0xff
for promotion to get the desired result.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.