2014-06-23 26 views
1

我有以下的代码:警告:左移位计数型的> =宽度[默认启用]

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:警告:左移计数> =宽度类型[默认启用] len =(buf [2] < < 56)| ^ math_fun.c:241:27:警告:左移计数> =类型宽度[默认启用] (buf [3] < < 48)| ^ math_fun.c:242:27:警告:左移计数> =宽度类型[默认启用] (buf [4] < < 40)| ^ math_fun.c:243:27:警告:左移计数> =宽度类型[默认启用] (buf [5] < < 32)|

如何解决警告?

+2

long int有多大?在转换之前施放到正确的类型。 – Deduplicator

+0

-bash-4.1 $ ./a.out long int的长度8 long long 8 unsigned long 8 –

+0

与[无符号整数位域移位产生带符号整数]密切相关(http://stackoverflow.com/questions/22152636/ unsigned-integer-bit-field-shift-yields-signed-integer/22152886#22152886),在栅栏上是否是dup。 –

回答

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

一个小细节并不会真正影响这个答案的质量,但是'buf [2]'几乎总是被提升为'int',而不是'unsigned int'。 –

+0

@MichaelBurr:好点。编辑。 – rici

+0

我不认为在C99中'unsigned char'和'int'一样宽。 'uint8_t'的存在似乎意味着'unsigned char'是8位宽,但是'int'必须比这更多。 –

0

请学习阅读的警告:

math_fun.c:240:21:警告:左移位计数型的> =宽度[默认启用] LEN =(BUF [2] < < 56) |^

这就给了你,你需要了解你的错误,以及如何解决它的所有信息:

你移小于56位长的类型,所以移56位或更多的是未定义行为
首先投射到适当大一点的类型。

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

当你在它的时候,考虑只使用unsigned那里类型,溢出signed类型是未定义的。

相关问题