Is negating INT_MIN undefined behaviour?

☆樱花仙子☆ 提交于 2019-12-04 12:33:05

It depends on the platform. C supports three representations for negative numbers (see section 6.2.6.2 of the C99 standard):

  • Two's complement.
  • One's complement.
  • Sign and magnitude.

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.

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.

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

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