警告:左移计数> =类型的宽度[默认启用]

时间:2014-06-23 00:12:03

标签: c int undefined-behavior bit-shift unsigned-char

我有以下代码:

long int compute_data_length(unsigned char* buf, int data_offset) {

long int len;

if(!buf)
    return -1;

switch(data_offset) {
    case 2: {
                len = (buf[2] << 8) | buf[3];
            }
            break;
    case 8: {
                len = (buf[2] << 56) |
                      (buf[3] << 48) |
                      (buf[4] << 40) |
                      (buf[5] << 32) |
                      (buf[6] << 24) |
                      (buf[7] << 16) |
                      (buf[8] <<  8) |
                      (buf[9]      );
            }
            break;
    default: len = -1; break;
}
return len;
}

编译时,我收到以下警告:

  

math_fun.c:240:21:警告:左移计数&gt; =类型宽度[默认启用]                        len =(buf [2]&lt;&lt; 56)|                        ^   math_fun.c:241:27:警告:左移计数&gt; =类型的宽度[默认启用]                              (buf [3]&lt;&lt; 48)|                              ^   math_fun.c:242:27:警告:左移计数&gt; =类型的宽度[默认启用]                              (buf [4]&lt;&lt; 40)|                              ^   math_fun.c:243:27:警告:左移计数&gt; =类型宽度[默认启用]                              (buf [5]&lt;&lt; 32)|

如何修复警告?

2 个答案:

答案 0 :(得分:5)

整数提升将buf[2] << 56转换为(int)buf[2] << 56 [注1],但int完全有可能只有32位,你需要它是无符号的64位类型转变是有意义的。

您希望unsigned long为64位,但可能不是。最好包含<stdint.h>并使用uint64_t。无论如何,你需要显式地转换左移的左操作数:

((uint64_t)buf[2] << 56) | ...

[注1]:unsigned char理论上可能与int一样宽,在这种情况下,整数提升将是unsigned int。但这只发生在不寻常的架构上。

答案 1 :(得分:0)

请学会阅读警告:

  

math_fun.c:240:21:警告:左移计数&gt; =类型的宽度[默认启用] len =(buf [2]&lt;&lt; 56)| ^

它为您提供了解错误所需的所有信息以及如何解决错误:

您移位的类型长度小于56位,因此移位56位或更多位是未定义的行为
首先选择适当的大型。

我希望long符合您平台上的帐单,因为这是您稍后将结果分配给的变量的类型。 int64_t将保证足够大,如果提供

当您在此时,请考虑仅使用unsigned类型,signed类型的溢出未定义。