假设我有一个变量i
,它来自外部来源:
int i = get_i();
假设
i
是INT_MIN
并采用二进制补码表示,那么-i
是否未定义?假设我有一个变量i
,它来自外部来源:
int i = get_i();
i
是INT_MIN
并采用二进制补码表示,那么-i
是否未定义?INT_MIN == -INT_MAX
那么 -INT_MIN == INT_MAX
,否则 -INT_MIN
是未定义行为。 - M.MINT_MIN == -INT_MAX
才会成立,而且这种情况甚至在二进制补码平台上也可能成立(至少在理论上是这样)。 - nwellnhof-INT_MIN
超出整数可表示的值范围时才有意义。如果您使用符号-大小或补码,则 -INT_MIN
在整数可表示的值范围内,因此 -INT_MIN
完全没有问题。当然,如果它溢出,如使用二补数时会发生,那么它是未定义的行为。 - CoffeeTableEspresso平台可以选择定义行为,但C标准不要求它们保证任何内容。历史上,微型计算机编译器的行为相对一致,好像-INT_MIN会产生INT_MIN或者某些情况下产生一个行为类似于比INT_MAX大1的值,但现在更流行的是对被否定的值进行追溯地更改。因此,如果有:
int wowzers(int x)
{
if (x != INT_MIN) printf("Not int min!");
return -x;
}
一种超现代编译器可能会使用表达式“-x”来确定在执行前一个比较时,x不能等于INT_MIN,并因此无条件地执行printf操作。
顺便说一句,gcc 8.2会利用将INT_MIN取反的UB性质来“优化”以下内容。
int qq,rr;
void test(unsigned short q)
{
for (int i=0; i<=q; i++)
{
qq=-2147483647-i;
rr=qq;
rr=-rr;
}
}
将代码转换为无条件将-2147483647存储到qq
和2147483647存储到rr
。删除rr=-rr
行将使代码将-2147483647或-2147483648存储到qq
和rr
中,具体取决于q
是否为零。
INT_MIN
的值时,在gcc 8.2中将影响另一个对象的存储值。 - supercatq
改为 -2147483646-i
,编译器的行为会变得更加有趣。生成的代码效率比将 rr=-rr
行替换为 rr=-(unsigned)rr
更低,因此编译器对 UB 的处理甚至不能提高代码效率。 - supercat负INT_MIN是否未定义行为?
是的,当INT_MIN < -INT_MAX
时,这非常常见(2的补码)。这是整数溢出。
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;