简体   繁体   中英

C/C++ Converting a 64 bit integer to char array

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:

  1. Drop the + : ... << test.c[idx] << ... . This may print the char as a character rather than a number, so is probably not a good solution.
  2. Declare c as unsigned char . This will promote it to an unsigned int .
  3. Explicitly cast +test.c[idx] before it is passed: ... << (unsigned char)(+test.c[idx]) << ...
  4. Set the upper bytes of the integer to zero using binary & : ... << +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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM