Skip to main content
Stack Overflow
  1. About
  2. For Teams

Return to Answer

Post Timeline

added C++20 note
Source Link
jwd
  • 11.4k
  • 4
  • 49
  • 78

This self-answer is just to spell things out, for future reference.

First, there is an assignment of a too-large unsigned value to a signed type:

int32_t x = 0x80000000U;

ThatBefore C++20 (see @shananton's comment), that is generally "implementation defined" behavior. Both Clang and GCC (all versions) perform the expected two's-compliment wraparound, here — but that's not guaranteed by the standard, before C++20.

So, x gets a value of -2147483648 (which is INT_MIN). You see this in the printout.

Then, the comparison of x == -x is made. But -x is undefined, for INT_MIN, since the result will not fit in the signed type.

With undefined behavior, the compiler is free to assume it can never happen. So, in this case, GCC optimizes away the path where they might be equal, since that undefined behavior is "not allowed" to happen.

This behavior can be altered with -fno-strict-overflow (which disables such optimizations), or with the even stronger -fwrapv, which makes signed integer overflow fully-defined.

This self-answer is just to spell things out, for future reference.

First, there is an assignment of a too-large unsigned value to a signed type:

int32_t x = 0x80000000U;

That is generally "implementation defined" behavior. Both Clang and GCC (all versions) perform the expected two's-compliment wraparound, here — but that's not guaranteed by the standard.

So, x gets a value of -2147483648 (which is INT_MIN). You see this in the printout.

Then, the comparison of x == -x is made. But -x is undefined, for INT_MIN, since the result will not fit in the signed type.

With undefined behavior, the compiler is free to assume it can never happen. So, in this case, GCC optimizes away the path where they might be equal, since that undefined behavior is "not allowed" to happen.

This behavior can be altered with -fno-strict-overflow (which disables such optimizations), or with the even stronger -fwrapv, which makes signed integer overflow fully-defined.

This self-answer is just to spell things out, for future reference.

First, there is an assignment of a too-large unsigned value to a signed type:

int32_t x = 0x80000000U;

Before C++20 (see @shananton's comment), that is generally "implementation defined" behavior. Both Clang and GCC (all versions) perform the expected two's-compliment wraparound, here — but that's not guaranteed by the standard, before C++20.

So, x gets a value of -2147483648 (which is INT_MIN). You see this in the printout.

Then, the comparison of x == -x is made. But -x is undefined, for INT_MIN, since the result will not fit in the signed type.

With undefined behavior, the compiler is free to assume it can never happen. So, in this case, GCC optimizes away the path where they might be equal, since that undefined behavior is "not allowed" to happen.

This behavior can be altered with -fno-strict-overflow (which disables such optimizations), or with the even stronger -fwrapv, which makes signed integer overflow fully-defined.

added 2 characters in body
Source Link
jwd
  • 11.4k
  • 4
  • 49
  • 78

This self-answer is just to spell things out, for future reference.

First, there is an assignment of a too-large unsigned value to a signed type:

int32_t x = 0x80000000U;

That is generally "implementation defined" behavior. Both Clang and GCC (all versions) perform the expected two's-compliment wraparound, here — but that's not guaranteed by the standard.

So, x gets a value of -2147483648 (which is INT_MIN). You see this in the printout.

Then, the comparison of x == -x is made. But -x is undefined, for INT_MIN, since the result will not fit in the signed type.

With undefined behavior, the compiler is free to assume it can never happen. So, in this case, GCC optimizes away the path where they might be equal, since that undefined behavior is not allowed"not allowed" to happen.

This behavior can be altered with -fno-strict-overflow (which disables such optimizations), or with the even stronger -fwrapv, which makes signed integer overflow fully-defined.

This self-answer is just to spell things out, for future reference.

First, there is an assignment of a too-large unsigned value to a signed type:

int32_t x = 0x80000000U;

That is generally "implementation defined" behavior. Both Clang and GCC (all versions) perform the expected two's-compliment wraparound, here — but that's not guaranteed by the standard.

So, x gets a value of -2147483648 (which is INT_MIN). You see this in the printout.

Then, the comparison of x == -x is made. But -x is undefined, for INT_MIN, since the result will not fit in the signed type.

With undefined behavior, the compiler is free to assume it can never happen. So, in this case, GCC optimizes away the path where they might be equal, since that undefined behavior is not allowed to happen.

This behavior can be altered with -fno-strict-overflow (which disables such optimizations), or with the even stronger -fwrapv, which makes signed integer overflow fully-defined.

This self-answer is just to spell things out, for future reference.

First, there is an assignment of a too-large unsigned value to a signed type:

int32_t x = 0x80000000U;

That is generally "implementation defined" behavior. Both Clang and GCC (all versions) perform the expected two's-compliment wraparound, here — but that's not guaranteed by the standard.

So, x gets a value of -2147483648 (which is INT_MIN). You see this in the printout.

Then, the comparison of x == -x is made. But -x is undefined, for INT_MIN, since the result will not fit in the signed type.

With undefined behavior, the compiler is free to assume it can never happen. So, in this case, GCC optimizes away the path where they might be equal, since that undefined behavior is "not allowed" to happen.

This behavior can be altered with -fno-strict-overflow (which disables such optimizations), or with the even stronger -fwrapv, which makes signed integer overflow fully-defined.

Source Link
jwd
  • 11.4k
  • 4
  • 49
  • 78

This self-answer is just to spell things out, for future reference.

First, there is an assignment of a too-large unsigned value to a signed type:

int32_t x = 0x80000000U;

That is generally "implementation defined" behavior. Both Clang and GCC (all versions) perform the expected two's-compliment wraparound, here — but that's not guaranteed by the standard.

So, x gets a value of -2147483648 (which is INT_MIN). You see this in the printout.

Then, the comparison of x == -x is made. But -x is undefined, for INT_MIN, since the result will not fit in the signed type.

With undefined behavior, the compiler is free to assume it can never happen. So, in this case, GCC optimizes away the path where they might be equal, since that undefined behavior is not allowed to happen.

This behavior can be altered with -fno-strict-overflow (which disables such optimizations), or with the even stronger -fwrapv, which makes signed integer overflow fully-defined.

lang-cpp

AltStyle によって変換されたページ (->オリジナル) /