提问人:H.S. 提问时间:8/31/2023 更新时间:8/31/2023 访问量:91
变量持有导致有符号整数溢出(后 incr. 的副作用)并且之后从未在任何表达式中使用它是否会导致 UB?
Does a variable holding result of signed integer overflow (side effect of post incr.) and, after that, never used it in any expression, result in UB?
问:
考虑这个程序
#include <limits.h>
int main (void) {
int i = 0;
// Assume, user is a fair person, following the instruction strictly..
printf ("Enter a number in the range [0 - INT_MAX] : \n");
scanf ("%d", &i);
while (i++ < INT_MAX) {
// do some stuff..
// value of variable i not used in loop body
}
// value of variable i is not used anywhere after loop body
return 0;
}
在循环条件的最后一次计算中,表达式中的值将是 ,但将保留 的结果(后递增的副作用),这本质上是有符号整数溢出。循环条件导致 IN 和循环退出。变量的值在程序中循环体之后的任何位置都没有使用,但当然,一旦循环退出,它就会保存 的结果。i++ < INT_MAX
i
INT_MAX
i
INT_MAX + 1
(INT_MAX < INT_MAX)
false
i
INT_MAX + 1
此程序是否具有未定义的行为?
附言:
- 我搜索了一下,发现了几个相关的问题,但它们并不完全相同:
does-integer-overflow-cause-undefined-behavior-because-of-memory-corruption
is-it-undefined-behavior-if-the-intermediate-result-of-an-expression-overflows
在上述两个问题中,导致溢出的变量/表达式的值以某种方式使用。
我的问题非常具体,并且指向未定义的行为,我不是在寻找任何其他方法来做示例程序中显示的事情。我非常清楚,如何避免UB。
如果您在帖子中包含引用(如果有),支持行为(无论是否为 UB),我将不胜感激。
答:
您似乎错误地认为未定义的行为意味着您的程序将以您可能意想不到的方式运行。那不是这个意思。
当一个程序包含未定义的行为时,C 标准不保证该程序将做什么。它可能会崩溃,可能会产生意外的结果,或者它可能看起来工作正常。
正如您从最初的研究中收集到的那样,有符号整数溢出确实是未定义的行为。您随后是否尝试使用并不重要。您的程序仍然具有未定义的行为。i
在这种特定情况下,你是否可能看到任何异常行为,可能不会,但同样不能保证这一点。
此程序是否具有未定义的行为?
是的,这很清楚。
您不必访问 after 溢出后的值即可发生溢出,并且一旦溢出发生,您就调用了未定义的行为。i
如果有人使用 GCC 编译您的程序并使用该标志,则您的程序将在溢出发生后立即崩溃,无论您后来是否尝试访问 .-ftrapv
i
评论
-ftrapv
GCC
如果您在帖子中包含引用(如果有),支持行为(无论是否为 UB),我将不胜感激。
C 2018 6.5.2.4 讨论了后缀。第 2 段说:++
...作为副作用,操作数对象的值将递增(即,将相应类型的值 1 添加到其中)。有关约束、类型和转换以及操作对指针的影响的信息,请参阅加法运算符和复合赋值的讨论...
6.5.6 讨论了加法运算符。第 5 段说:
二进制运算符的结果是操作数的总和。
+
6.5 第 5 段说:
如果在计算表达式期间发生异常情况(即,如果结果未以数学方式定义或不在其类型的可表示值范围内),则该行为未定义。
因此,当用等于计算时,它有效地计算,并且发生异常情况,因此程序的行为不是由C标准定义的。i++
i
INT_MAX
INT_MAX + 1
评论
i