C/C++ 将 64 位整数转换为字符数组

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

我有以下简单程序,它使用联合在 64 位整数与其对应的字节数组之间进行转换:

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;
}

我期望的输出是:

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

但我实际得到的是:

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

我在 Ubuntu LTS 14.04 with GCC 上看到了这个。

一段时间以来,我一直在努力解决这个问题。为什么 char 数组的前 4 个元素显示为 32 位整数,并在它们前面加上 0xffffff?为什么只有前 4 个,为什么不是全部?
有趣的是,当我使用数组写入流(这是整个事情的最初目的)时,写入了正确的值。但是逐个字符比较数组显然会导致问题,因为前 4 个字符不等于 0xef、0xcd 等等。

它是 unsigned char 与 signed char 及其转换为整数

使用 unsigned char 或使用 test.c[idx] & 0xff 以避免在将 char value > 0x7f 转换为 int 时进行符号扩展。

使用 char 不是正确的做法,因为它可能是 signedunsigned。使用 unsigned char.

union u
{
  uint64_t ui;
  unsigned char c[sizeof(uint64_t)];
};

一元加号导致 char 提升为 int(整数提升)。因为您已经签署了字符,所以该值将按原样使用,其他字节将反映出来。

不是只有这四个是int,它们都是。您只是从表示中看不到它,因为未显示前导零。

使用 unsigned char& 0xff 进行推广以获得理想的结果。

char 由于前置的一元运算符 + 被提升为 int。 .由于您的 charssigned,任何具有最高 by 设置为 1 的元素都被解释为负数并提升为具有相同负值的整数。有几种不同的方法可以解决这个问题:

  1. 删除 +... << test.c[idx] << ...。这可能会将 char 打印为字符而不是数字,因此可能不是一个好的解决方案。
  2. 声明 cunsigned char。这会将其提升为 unsigned int.
  3. 在传递之前显式转换+test.c[idx]... << (unsigned char)(+test.c[idx]) << ...
  4. 使用二进制 & 将整数的高位字节设置为零:... << +test.c[idx] & 0xFF << ...。无论 char 如何提升,这只会显示最低位字节。