Bitwise shift operation in C on uint64_t variable

前端 未结 4 2058
半阙折子戏
半阙折子戏 2021-01-20 02:21

I have the following sample code:

uint64_t x, y;
x = ~(0xF<<24);
y = ~(0xFF<<24);

The result would be:

x=0xffff         


        
4条回答
  •  天命终不由人
    2021-01-20 03:06

    You have undefined behavior in your program so anything might happen.

    • The integer literals 0xF or 0xFF are of type int, which is equivalent to signed int. On this particular platform, int is apparently 32 bits.
    • The integer literal 24 is also a (signed) int.
    • When the compiler evaluates the << operation, both operands are (signed) int so no implicit type promotions take place. The result of the << operation is therefore also a (signed) int.
    • The value 0xF<<24 = 0x0F000000 fits in a (signed) int as a non-negative value, so everything is ok.
    • The value 0xFF<<24 = 0xFF000000 does not fit in (signed) int! Here, undefined behavior is invoked and anything might happen.

    ISO 9899:2011 6.5.7/4:

    "The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros." /--/

    "If E1 has a signed type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

    So the expression 0xFF<<24 can't be used. The program is free to print any garbage value after that.

    But if we ignore that one and focus on 0x0F<24:

    • 0x0F000000 is still a (signed) int. The ~operator is applied to this.
    • The result is 0xF0FFFFFF, which is still a signed int. And on almost any system, this 32-bit hex equals a negative number in two's complement.
    • This signed int is converted to the type uint64_t during assignment. This is done in two steps, first by converting it to a signed 64 bit, then by converting that signed 64 to an unsigned 64.

    Bugs like this is why the coding standard MISRA-C contains a number of rules to ban sloppy use of integer literals in expression like this. MISRA-C compliant code must use the u suffix after each integer literal (MISRA-C:2004 10.6) and the code is not allowed to perform bitwise operations on signed integers (MISRA-C:2004 12.7).

提交回复
热议问题