Is 1 << 31 well defined in C when sizeof(int) == 4

倾然丶 夕夏残阳落幕 提交于 2019-11-29 01:52:10

问题


According to the answer to this questions:

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. 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.

Which seems to imply that 1 << 31 is undefined.

However GCC doesn't issue a warning if I use 1 << 31. It does issue one for 1 << 32. link

So which is it? Am I misunderstanding the standard? Does GCC have its own interpretation?


回答1:


No: 1 << 31 has undefined behavior if the type int has only 31 value bits.

1U << 31 is OK and evaluates to 0x80000000 if type unsigned int has 32 value bits.

On a system where bytes have 8 bits, sizeof(int) == 4 means int has at most 31 value bits, so shifting 1 by 31 places is undefined. Conversely, on a system where CHAR_BIT > 8, it may be OK to write 1 << 31.

gcc might issue a warning if you raise the warning level. try gcc -Wall -Wextra -W -Werror. clang does issue a warning with the same options.

To address Michaël Roy's comments, 1 << 31 does not evaluate to INT_MIN reliably. It might give this value on your system, but the Standard does not guarantee it, in fact the Standard describes this as undefined behavior, so not only can you not rely on it, you should avoid it to avoid spurious bugs. The optimizers routinely take advantage of potential undefined behavior to remove code and break the programmers' assumptions.

For example, the following code might compile to a simple return 1;:

int check_shift(int i) {
   if ((1 << i) > 0)
       return 1;
   else
       return 0;
}

None of the compilers supported by Godbolt's compiler explorer do, but doing so would not break conformity.




回答2:


The reason GCC doesn't warn about this is because 1 << 31 was valid (but implementation-defined) in C90, and is valid (but implementation-defined) even in modern C++. C90 defines << as a bit shift and followed by saying that for unsigned types, its result was that of a multiplication, but did no such thing for signed types, which implicitly made it valid and left it covered by the general wording that bitwise operators have implementation-defined aspects for signed types. C++ nowadays defines << as multiplying to the corresponding unsigned type, with the result converted back to the signed type, which is implementation-defined as well.

C99 and C11 did make this invalid (saying the behaviour is undefined), but compilers are permitted to accept it as an extension. For compatibility with existing code, and to share code between the C and C++ frontends, GCC continues to do so, with one exception: you can use -fsanitize=undefined to get detected undefined behaviour to abort your program at run-time, and this one does handle 1 << 31, but only when compiling as C99 or C11.




回答3:


It does invoke undefined behaviour, as explained by the other answers/comments. However, as to why GCC doesn't emit a diagnostic.

There are actually two things that can lead to undefined behaviour for a left-shift (both from [6.5.7]):

  1. 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.

  2. 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.

Evidently GCC detects the first one (because it's trivial to do so), but not the latter.



来源:https://stackoverflow.com/questions/45268467/is-1-31-well-defined-in-c-when-sizeofint-4

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