否定 INT_MIN 未定义的行为?
Is negating INT_MIN undefined behaviour?
假设我有一个来自外部来源的变量 i
:
int i = get_i();
假设i
是INT_MIN
和二进制补码表示,-i
是否未定义?
这取决于平台。 C支持负数的三种表示法(见C99标准的section 6.2.6.2):
- 补码。
- 一个补码。
- 符号和大小。
用补码和符号和大小,定义-INT_MIN
(等于INT_MAX
)。对于二进制补码,它取决于符号位为 1 且所有值位为零的值是陷阱表示还是正常值。如果它是一个正常值,-INT_MIN
溢出,导致未定义的行为(参见 C99 标准的 section 6.5)。如果是陷阱表示,-INT_MIN
等于 INT_MAX
.
也就是说,大多数现代平台使用二进制补码而不使用陷阱表示,因此 -INT_MIN
通常会导致未定义的行为。
平台可以选择定义行为,但 C 标准不要求它们对此做出任何保证。虽然从历史上看,微型计算机编译器的行为相对一致,就好像 -INT_MIN 会产生 INT_MIN 或在某些情况下,一个数字的行为类似于比 INT_MAX 大一的值,但现在变得更流行了它追溯 改变任何被否定的值。因此,给定:
int wowzers(int x)
{
if (x != INT_MIN) printf("Not int min!");
return -x;
}
超现代编译器可能会使用表达式 -x 来确定 x 不能
执行上一次比较时等于 INT_MIN,并且
因此可以无条件地执行 printf。
顺便说一句,gcc 8.2 将使用 UB-ness 否定 INT_MIN 到 "optimize" 以下
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
是否为零。
Is negating INT_MIN undefined behaviour?
是的,当 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;
假设我有一个来自外部来源的变量 i
:
int i = get_i();
假设i
是INT_MIN
和二进制补码表示,-i
是否未定义?
这取决于平台。 C支持负数的三种表示法(见C99标准的section 6.2.6.2):
- 补码。
- 一个补码。
- 符号和大小。
用补码和符号和大小,定义-INT_MIN
(等于INT_MAX
)。对于二进制补码,它取决于符号位为 1 且所有值位为零的值是陷阱表示还是正常值。如果它是一个正常值,-INT_MIN
溢出,导致未定义的行为(参见 C99 标准的 section 6.5)。如果是陷阱表示,-INT_MIN
等于 INT_MAX
.
也就是说,大多数现代平台使用二进制补码而不使用陷阱表示,因此 -INT_MIN
通常会导致未定义的行为。
平台可以选择定义行为,但 C 标准不要求它们对此做出任何保证。虽然从历史上看,微型计算机编译器的行为相对一致,就好像 -INT_MIN 会产生 INT_MIN 或在某些情况下,一个数字的行为类似于比 INT_MAX 大一的值,但现在变得更流行了它追溯 改变任何被否定的值。因此,给定:
int wowzers(int x)
{
if (x != INT_MIN) printf("Not int min!");
return -x;
}
超现代编译器可能会使用表达式 -x 来确定 x 不能 执行上一次比较时等于 INT_MIN,并且 因此可以无条件地执行 printf。
顺便说一句,gcc 8.2 将使用 UB-ness 否定 INT_MIN 到 "optimize" 以下
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
是否为零。
Is negating INT_MIN undefined behaviour?
是的,当 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;