简体   繁体   English

移位计数大于类型的宽度

[英]shift count greater than width of type

I have a function that takes an int data_length and does the following: 我有一个函数,它需要一个int data_length并执行以下操作:

unsigned char *message = (unsigned char*)malloc(65535 * sizeof(char));
message[2] = (unsigned char)((data_length >> 56) & 255);

I'm getting the following: 我得到以下内容:

warning: right shift count >= width of type [-Wshift-count-overflow]
   message[2] = (unsigned char)((data_length >> 56) & 255);

The program works as expected, but how can I remove the compiler warning (without disabling it)? 该程序可以按预期工作,但是如何删除编译器警告(不禁用它)? Similar questions didn't seem to use a variable as the data to be inserted so it seemed the solution was to cast them to int or such. 类似的问题似乎没有使用变量作为要插入的数据,因此似乎解决方案是将其强制转换为int或此类。

Shifting by an amount greater than the bit width of the type in question is not allowed by the standard, and doing so invokes undefined behavior . 标准不允许移位大于所讨论类型的位宽的量,并且这样做会引起未定义的行为

This is detailed in section 6.5.7p3 of the C standard regarding bitwise shift operators. C标准的 6.5.7p3节中有关于位移位运算符的详细信息。

The integer promotions are performed on each of the operands. 对每个操作数执行整数提升。 The type of the result is that of the promoted left operand. 结果的类型是提升后的左操作数的类型。 If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined. 如果右操作数的值为负或大于或等于提升的左操作数的宽度,则行为是不确定的。

If the program appears to be working, it is by luck. 如果该程序似乎正在运行,则很幸运。 You could make a unrelated change to your program or simply build it on a different machine and suddenly things will stop working. 您可以对程序进行不相关的更改,也可以仅在其他计算机上构建它,然后突然一切都停止了。

If the size of data_length is 32 bits or less, then shifting right by 56 is too big. 如果data_length的大小为32位或更小,则右移56位太大。 You can only shift by 0 - 31. 您只能平移0-31。

The problem is simple. 问题很简单。 You're using data_length as int when it should be unsigned as negative lengths hardly make sense. 当使用data_length进行无符号化(因为负长度几乎没有意义)时,您将其用作int Also to be able to shift 56 bits the value must be at least 56 57 bits wide. 为了能够移位56位,该值必须至少为56 57位宽。 Otherwise the behaviour is undefined. 否则,行为是不确定的。

In practice processors are known to do wildly different things. 在实践中,已知处理器会做很多不同的事情。 In one, shifting a 32-bit value right by 32 bits will clear the variable. 在一个例子中,将32位值右移32位将清除变量。 In another, the value is shifted by 0 bits ( 32 % 32 !). 在另一个值中,该值移位了0位( 32 % 32 !)。 And then in some, perhaps the processor considers it invalid opcode and the OS kills the process. 然后,在某些情况下,也许处理器认为它是无效的操作码,而OS终止了该进程。

Simple solution: declare uint64_t data_length . 简单的解决方案:声明uint64_t data_length


If you really have limited yourself to 32-bit datatypes, then you can just assign 0 to these bytes that signify the most significant bytes. 如果你真的有自己限制在32位数据类型,那么你可以指定0到这些字节即表示最显著字节。 Or just cast to uint64_t or unsigned long long before the shift. 或者只是在转换前unsigned long longuint64_t转换为uint64_tunsigned long long

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM