我有一个使用int data_length
并执行以下操作的函数:
unsigned char *message = (unsigned char*)malloc(65535 * sizeof(char));
message[2] = (unsigned char)((data_length >> 56) & 255);
我得到以下信息:
warning: right shift count >= width of type [-Wshift-count-overflow]
message[2] = (unsigned char)((data_length >> 56) & 255);
程序可以按预期工作,但是如何删除编译器警告(不禁用它)? 类似的问题似乎没有使用变量作为要插入的数据,因此似乎解决方案是将其强制转换为int或此类。
答案 0 :(得分:2)
标准不允许移动大于所讨论类型的位宽的量,并且这样做会调用undefined behavior。
这在C standard的6.5.7p3节中详细介绍了按位移位运算符。
对每个操作数执行整数提升。的 结果的类型是提升后的左操作数的类型。如果 右操作数的值是负数或大于 或等于提升的左操作数的宽度,其行为是 未定义。
如果程序似乎正在运行,很幸运。您可以对程序进行不相关的更改,也可以仅在其他计算机上构建它,然后突然一切停止运转。
如果data_length
的大小为32位或更小,则向右移56将太大。您只能平移0-31。
答案 1 :(得分:1)
问题很简单。当您将data_length
用作int
时,应该使用 unsigned ,因为负长度几乎没有意义。为了能够移位56位,值必须至少宽 56 57位。否则,行为是不确定的。
在实践中,处理器的功能千差万别。在一个例子中,将32位值右移32位将清除变量。在另一个值中,该值移位0位(32 % 32
!)。然后,在某些情况下,也许处理器认为它是无效的操作码,并且操作系统终止了该进程。
简单的解决方案:声明uint64_t data_length
。
如果您确实将自己限制为32位数据类型,则只需将0分配给这些表示最高有效字节的字节即可。或者只是在转换前强制转换为uint64_t
或unsigned long long
。