简体   繁体   中英

shift count greater than width of type

I have a function that takes an int data_length and does the following:

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.

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.

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. You can only shift by 0 - 31.

The problem is simple. You're using data_length as int when it should be unsigned as negative lengths hardly make sense. Also to be able to shift 56 bits the value must be at least 56 57 bits wide. 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. In another, the value is shifted by 0 bits ( 32 % 32 !). And then in some, perhaps the processor considers it invalid opcode and the OS kills the process.

Simple solution: declare 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. Or just cast to uint64_t or unsigned long long before the shift.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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