【问题标题】:C/C++ Converting a 64 bit integer to char arrayC/C++ 将 64 位整数转换为 char 数组
【发布时间】:2015-09-01 15:35:02
【问题描述】:

我有以下简单的程序,它使用联合在 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

我在带有 GCC 的 Ubuntu LTS 14.04 上看到了这一点。

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

【问题讨论】:

  • 转换为(char*) 然后读取4个字节...?
  • 没有变化。此外,我总是可以用 0x000000ff 屏蔽字符以获得预期值。我只是对这种行为背后的原因感兴趣。
  • 显然您的实现已签名字符。普通整数提升将符号扩展。
  • 我认为这是因为 test.c 是 int 类型,这将是 16 位、32 位或 64 位字,具体取决于内核构建的体系结构......有点不过,猜测一下,我需要掸掉我的 C++ 帽子!此外,对于 @ewd 的评论,您可能希望将其明确转换为 (unsigned int)(unsigned char)
  • 嘿,解决了!谢谢!

标签: c++ gcc memory 64-bit


【解决方案1】:

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

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

【讨论】:

  • 这样就解决了。现在的问题是,将数组写入流会产生错误,因为流只接受char * 而不是unsigned char *,而且我不太喜欢一直使用reinterpret_cast...
  • @tickferno,如果您需要帮助,请发布另一个专门解决流媒体问题的问题。
【解决方案2】:

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

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

【讨论】:

  • char 在
  • 删除一元 + 运算符会“直接”打印字符,但我对它们的实际十六进制值感兴趣(否则十六进制运算符无济于事)。以下也失败了:test.c[0] == 0xef
  • 好电话。相应地进行了编辑。
【解决方案3】:

char value &gt; 0x7f 转换为 int 时,使用 unsigned char 或使用 test.c[idx] &amp; 0xff 以避免符号扩展。

【讨论】:

    【解决方案4】:

    它是无符号字符与有符号字符及其转换为整数

    【讨论】:

      【解决方案5】:

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

      只有四个是整数是不正确的,它们都是。您只是没有从表示中看到它,因为没有显示前导零。

      使用unsigned chars 或&amp; 0xff 进行促销以获得所需的结果。

      【讨论】:

        猜你喜欢
        • 2016-04-30
        • 1970-01-01
        • 1970-01-01
        • 2017-10-08
        • 1970-01-01
        • 1970-01-01
        • 2016-02-27
        • 1970-01-01
        • 2015-01-27
        相关资源
        最近更新 更多