c - 如何测试序列点未定义行为的规则?

标签 c undefined-behavior

我从 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/

相关文章:

c - 在 C 中分配一个 int 数组,但得到一个额外的 int 32767

C 函数返回一个指向局部变量的指针

c++ - 是vector.push_back(vector.back()+ 1)未定义的行为吗?

c - 没有默认大小写的 Objective-C 枚举 "exhaustive"开关的行为

C编程。打印当前用户

fortran - 是否允许为另一个过程的可选参数传递一个不存在的假定形状数组?

c - 与 const 和非常量成员 union

c - 对结构成员的不优雅访问

c - 使用pmap分析进程的内存映射。 [堆栈]

c - 我以各种可能的方式尝试了这段代码,但我找不到为什么?