变量持有导致有符号整数溢出(后 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?

提问人:H.S. 提问时间:8/31/2023 更新时间:8/31/2023 访问量:91

问:

考虑这个程序

#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_MAXiINT_MAXiINT_MAX + 1(INT_MAX < INT_MAX)falseiINT_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 整数溢出 后增量

评论

0赞 President James K. Polk 8/31/2023
这回答了你的问题吗?C 整数溢出
0赞 H.S. 8/31/2023
@PresidentJamesK.波尔克:我知道。我的问题特定于循环条件。请注意,变量在循环体和循环后的任何位置都未使用。i
2赞 stark 8/31/2023
MIPS 有符号加法在溢出 stackoverflow.com/q/9559145/1216776 时生成异常
0赞 Lundin 8/31/2023
@stark 可以说,这不是任何 ISA 所期望的行为。任何理智的 ISA 在发现有符号溢出时只会举起一个标志,并且仍然会产生确定性的结果 - 2 的补码环绕。尽管签名溢出可能是一个错误,但很少有程序员希望该错误的结果“崩溃并烧毁”。通知程序员一个错误和故意使最终应用程序崩溃是两回事。

答:

2赞 dbush 8/31/2023 #1

您似乎错误地认为未定义的行为意味着您的程序将以您可能意想不到的方式运行。那不是这个意思。

当一个程序包含未定义的行为时,C 标准不保证该程序将做什么。它可能会崩溃,可能会产生意外的结果,或者它可能看起来工作正常。

正如您从最初的研究中收集到的那样,有符号整数溢出确实是未定义的行为。您随后是否尝试使用并不重要。您的程序仍然具有未定义的行为。i

在这种特定情况下,你是否可能看到任何异常行为,可能不会,但同样不能保证这一点。

3赞 user229044 8/31/2023 #2

此程序是否具有未定义的行为?

是的,这很清楚。

您不必访问 after 溢出后的值即可发生溢出,并且一旦溢出发生,您就调用了未定义的行为。i

如果有人使用 GCC 编译您的程序并使用该标志,则您的程序将在溢出发生后立即崩溃,无论您后来是否尝试访问 .-ftrapvi

评论

1赞 H.S. 8/31/2023
谢谢。我不知道.-ftrapvGCC
3赞 Eric Postpischil 8/31/2023 #3

如果您在帖子中包含引用(如果有),支持行为(无论是否为 UB),我将不胜感激。

C 2018 6.5.2.4 讨论了后缀。第 2 段说:++

...作为副作用,操作数对象的值将递增(即,将相应类型的值 1 添加到其中)。有关约束、类型和转换以及操作对指针的影响的信息,请参阅加法运算符和复合赋值的讨论...

6.5.6 讨论了加法运算符。第 5 段说:

二进制运算符的结果是操作数的总和。+

6.5 第 5 段说:

如果在计算表达式期间发生异常情况(即,如果结果未以数学方式定义或不在其类型的可表示值范围内),则该行为未定义。

因此,当用等于计算时,它有效地计算,并且发生异常情况,因此程序的行为不是由C标准定义的。i++iINT_MAXINT_MAX + 1