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

C++ C/C++;将64位整数转换为字符数组,c++,gcc,memory,64-bit,C++,Gcc,Memory,64 Bit,我有一个简单的程序,它使用并集在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++) { co

我有一个简单的程序,它使用并集在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] = 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
我在UbuntuLTS14.04和GCC上看到了这一点

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

这是无符号字符与有符号字符的比较,它的转换为整数。

使用无符号字符或使用
test.c[idx]&0xff
在将
字符值>0x7f
转换为int时避免符号扩展。

使用
字符
不是正确的做法,因为它可能是
有符号的
无符号的
。使用
无符号字符

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

一元加号使
char
提升为
int
(整体提升)。由于您已对字符进行了签名,因此将使用该值,其他字节将反映这一点

并非只有四个整数是整数,它们都是整数。因为没有显示前导零,所以从表示中看不到它


使用
unsigned char
s或
&0xff
进行升级以获得所需的结果。

char
由于前面加了一元运算符
+
而升级为
int
。由于
字符
是有符号的,因此将最高by设置为
1
的任何元素都将被解释为负数,并提升为具有相同负值的整数。有几种不同的方法可以解决此问题:


  • 放下
    +
    。。。转换为
    (char*)
    ,然后读取4个字节…?无更改。此外,我可以始终使用0x000000ff屏蔽字符以获得期望值。我只是对这种行为背后的原因感兴趣。显然,您的实现已经签署了chars。正常的整数提升将符号扩展。我认为这是因为test.c是类型
    int
    ,它将是16位、32位或64位字,具体取决于内核构建的体系结构。。。有点猜测,但我需要掸去我的C++帽子!此外,在@ewd的注释之后,您可能希望将其具体转换为
    (unsigned int)
    (unsigned char)
    。嘿,这就解决了它!谢谢char在删除时不会被提升,一元+运算符“直接”打印char,但我对它们的实际十六进制值感兴趣(十六进制运算符在其他方面没有帮助)。同样,以下操作失败:
    test.c[0]==0xef
    Good call。相应地编辑。这就解决了它。现在的问题是,将数组写入流会产生错误,因为流只接受
    char*
    而不接受
    unsigned char*
    ,而且我真的不喜欢一直使用
    reinterpret\u cast
    。@tickferno,如果您需要帮助,请发布另一个专门解决流问题的问题。
    union u
    {
      uint64_t ui;
      unsigned char c[sizeof(uint64_t)];
    };