Is unsigned long int correct for this operation?

天涯浪子 提交于 2019-11-28 11:38:48

问题


Here's my code:

#include <stdio.h>

int main(int argc, char *argv[]) {

    unsigned long int x = 0;

    // trying to make x = 2,147,483,648
    x = 1 << 31;

    printf("%lu", x);
}

It's returning that x = 18446744071562067968. I read that unsigned long int should go up to 4,294,967,296, so why can't I use 1 << 32 to set x equal to 2,147,483,648?


回答1:


1 << 31 causes undefined behaviour, if your system has 32-bit ints. The literal 1 is a signed int.

You need to do an unsigned shift instead of a signed shift:

x = 1UL << 31;

I added L so that the code is still correct even on a 16-bit system, and it doesn't hurt to do so.


Informally, shifting a 1 into the sign bit is undefined. The formal text can be found in section 6.5.7/4 of the C11 standard:

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.


Your other question, "why can't I use 1 << 32" is covered by that same quote. What about 1UL << 32 ? If your system has 32-bit unsigned long then this would also be undefined according to 6.5.7/3:

[...] 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

But it would work if your system had 64-bit unsigned long. To avoid having your code break when compiled on a different system (this goal is known as code portability) you could write (uint64_t)1 << 32 (or 1ULL << 32) which is guaranteed to work.



来源:https://stackoverflow.com/questions/35119136/is-unsigned-long-int-correct-for-this-operation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!