【问题标题】:c++ - warning: right shift count >= width of type on 32 bit machinec ++ - 警告:右移计数> = 32位机器上的类型宽度
【发布时间】:2014-05-09 14:56:02
【问题描述】:

我有以下功能:

void func(unsigned long v)
{
  char max_byte = 0xFF;
  char buffer[8];

  buffer[0] = static_cast<char>((v)       & max_byte);
  buffer[1] = static_cast<char>((v >> 8)  & max_byte);
  buffer[2] = static_cast<char>((v >> 16) & max_byte);
  buffer[3] = static_cast<char>((v >> 24) & max_byte);
  buffer[4] = static_cast<char>((v >> 32) & max_byte);
  buffer[5] = static_cast<char>((v >> 40) & max_byte);
  buffer[6] = static_cast<char>((v >> 48) & max_byte);
  buffer[7] = static_cast<char>((v >> 56) & max_byte);
}

它接受一个unsigned long 参数并将其8 个字节插入char 缓冲区(不要试图找出原因。它是一个有意义的函数的简明版本)。

此代码在 64 位上编译良好,但在 32 位上我收到以下警告:

warning: right shift count >= width of type

指行:

  buffer[4] = static_cast<char>((v >> 32) & max_byte);
  buffer[5] = static_cast<char>((v >> 40) & max_byte);
  buffer[6] = static_cast<char>((v >> 48) & max_byte);
  buffer[7] = static_cast<char>((v >> 56) & max_byte);

我想我理解了这个警告,但我不确定我应该怎么做才能在 32 位上顺利编译它。

【问题讨论】:

  • 是的,是undefined behavior执行宽度大于或等于位数的移位。
  • unsigned long 在 32 位系统上的长度是多少?
  • @ShafikYaghmour 我明白,但解决方案是什么。 unsigned long 长度为 64 位,我需要正确处理。
  • 让我们谈谈轮班运算符 > - viva64.com/en/b/0142

标签: c++ 32bit-64bit bit-shift unsigned-integer


【解决方案1】:

使用fixed-width integer types。在这种情况下,您需要std::uint64_t

【讨论】:

  • 或者至少 try,实现不需要提供这些 :) 但是是的,这就是解决方案。
【解决方案2】:

unsigned long 只保证有 32 位。见here。您需要使用 unsigned long long 来保证 64 位。

最好使用fixed width integer,即uint64_t。它们在标题&lt;cstdint&gt;(或&lt;stdint.h&gt;)中定义。

【讨论】:

  • "也在 C++ 的早期版本中" - 仅当您的库/编译器具有非标准扩展时。它们直到 C++11 才成为标准。
【解决方案3】:

在编写依赖于整数大小的代码时,您确实需要使用&lt;stdint.h&gt;

#include <stdint.h>

void func(uint64_t v)
{
  static const uint8_t max_byte = 0xFF; // Let the compiler hardcode this constant.
  uint8_t buffer[8];

  buffer[0] = static_cast<uint8_t>((v)       & max_byte);
  buffer[1] = static_cast<uint8_t>((v >> 8)  & max_byte);
  buffer[2] = static_cast<uint8_t>((v >> 16) & max_byte);
  buffer[3] = static_cast<uint8_t>((v >> 24) & max_byte);
  buffer[4] = static_cast<uint8_t>((v >> 32) & max_byte);
  buffer[5] = static_cast<uint8_t>((v >> 40) & max_byte);
  buffer[6] = static_cast<uint8_t>((v >> 48) & max_byte);
  buffer[7] = static_cast<uint8_t>((v >> 56) & max_byte);
}

【讨论】:

  • 今天不是我的日子。当我试图发布时,调制解调器失去了连接。 >_
【解决方案4】:

我的假设可能是错误的,即没有一个答案能真正触及这个问题的重点,因此这里继续。

编译为 64 位二进制长整型定义为 64 位值(或 8 个字节),而 32 位二进制长整型与 32 位或 4 字节的 int 相同。

这个问题有几种解决方法:
1. 按照其他回复中的建议,将参数重新定义为 long long 或 int64。
2. 添加预处理器定义以阻止有问题的位操作。比如……

#ifdef __LP64__
buffer[4] = static_cast<uint8_t>((v >> 32) & max_byte);
buffer[5] = static_cast<uint8_t>((v >> 40) & max_byte);
buffer[6] = static_cast<uint8_t>((v >> 48) & max_byte);
buffer[7] = static_cast<uint8_t>((v >> 56) & max_byte);
#endif


这将确保根据处理器体系结构处理 long,而不是强制 long 始终为 64 位。
3. 对于提供的代码,使用联合也可以实现相同的最终结果

void func(unsigned long v)
{
    union {
        unsigned long long  ival;
        unsigned char       cval[8];
    } a;

    a.ival = v;
}

当然,如果您使用 c++,那么您可以通过修改上述内容以类似的方式存储任何基本数据类型:

template<class I>
void func(I v) {
    union {
        unsigned long long  ival;
        unsigned char       cval[8];
        I                   val;
    } a;

    a.val = v;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多