我从 2 天开始阅读有关 UB 的内容,我对以下示例越来越感到困惑
int a=5;
a++ & printf("%d",a);//i know that `&` introduced here is not a sequence point.
现在,它是 c 中的 UB,但我从另一个角度看它,如下所示
现在c标准说
在前一个和下一个序列点之间,对象的存储值最多应通过表达式的计算修改一次。
因此,由于我们仅通过编写一次 a++
来修改 a 的值,因此该规则无法将行为声明为 UB。
但它进一步指出
此外,仅应访问先前值以确定要存储的值。
由于 a
的先验值(此处为 5 )通过 a++
访问以写入 a
的值。但是在语句 printf("%d",a)
("%d",a)
是一个完整的表达式。因此,在表达式运行之前,应该解决所有副作用的问题
。
按照标准
当进行函数调用时,在实际调用之前和参数求值之后存在序列点。
所以a
应该是在函数调用这里修改的,更准确的说a
的值是按照标准更新的。
那么为什么它仍然是 UB,因为 ("%d",a)
本身就是一个表达式,它在 ;
之前求值?
最佳答案
("%d",a)
不是完整表达式。在这种情况下,它甚至不是一个表达。它是函数的参数列表。代码中的完整表达式是第二行中的所有内容,;
除外。
A full expression is an expression that is not part of another expression or of a declarator.
a
在参数列表中的访问在它和 a++
之间没有插入序列点,它不是为了做 a++
,因此行为未定义。
关于c - 如何测试序列点未定义行为的规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22626269/