Let\'s say I have a variable i
that comes from external sources:
int i = get_i();
Assuming i
is INT_MIN
Is negating INT_MIN undefined behaviour?
Yes, when INT_MIN < -INT_MAX
- which is very common (2's complement). It is integer overflow.
int i = get_i();
#if INT_MIN < -INT_MAX
if (i == INT_MIN) {
fprintf(stderr, "Houston, we have a problem\n");
// Maybe return or exit here.
}
#endif
int j = -i;
Houston, we have a problem
Platforms may choose to define the behavior, but the C Standard does not require that they guarantee anything about it. While historically microcomputer compilers have relatively consistently behaved as though -INT_MIN would yield INT_MIN or in some cases a number that behaves like a value one larger than INT_MAX, it has become more fashionable to instead have it retroactively change the value of whatever was being negated. Thus, given:
int wowzers(int x)
{
if (x != INT_MIN) printf("Not int min!");
return -x;
}
a hyper-modern compiler may use the expression -x to determine that x can't have been equal to INT_MIN when the previous comparison was performed, and may thus perform the printf unconditionally.
Incidentally, gcc 8.2 will use the UB-ness of negating INT_MIN to "optimize" the following
int qq,rr;
void test(unsigned short q)
{
for (int i=0; i<=q; i++)
{
qq=-2147483647-i;
rr=qq;
rr=-rr;
}
}
into code that unconditionally stores -2147483647 to qq
and 2147483647 to rr
. Removing the rr=-rr
line will make the code store -2147483647 or -2147483648 into both qq
and rr
, depending upon whether q
is zero.
It depends on the platform. C supports three representations for negative numbers (see section 6.2.6.2 of the C99 standard):
With one's complement and sign and magnitude, -INT_MIN
is defined (and equal to INT_MAX
). With two's complement, it depends on whether the value with sign bit 1 and all value bits zero is a trap representation or a normal value. If it's a normal value, -INT_MIN
overflows, resulting in undefined behavior (see section 6.5 of the C99 standard). If it's a trap representation, -INT_MIN
equals INT_MAX
.
That said, most modern platforms use two's complement without trap representations, so -INT_MIN
typically results in undefined behavior.