c ++ - 警告:右移计数> = 32位机器上的类型宽度

时间:2014-05-09 14:56:03

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

我有以下功能:

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位上顺利编译它。

4 个答案:

答案 0 :(得分:8)

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

答案 1 :(得分:5)

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

更好的方法是使用fixed width integer,即uint64_t。它们在标题<cstdint>(或<stdint.h>)中定义。

答案 2 :(得分:2)

编写依赖于整数大小的代码时,您确实需要使用<stdint.h>

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

答案 3 :(得分:0)

我可能错误地认为没有一个答案真正达到了这个问题的重点,因此这里就是这样。

编译为64位二进制文​​件时,long定义为64位值(或8字节),而32位二进制文​​件a long与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,而不是强制长到64位 3.对于提供的代码

,使用union也可以实现相同的最终结果
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;
}