6

我对整个序列点的理解是基本的。我所拥有的只是一些粗略的直观想法,即“一旦遇到序列点,我们可以确定之前评估的所有副作用都是完整的”。我还读到,在printf("%d",a++,++a,a++)行为未定义之类的语句中,逗号不表示序列点,而分号表示。因此,与其凭直觉进行猜测和猜测,我觉得一个非常严谨和确凿的答案会对我有很大帮助。

以下类型的语句在 C 中是安全且确定的:

int a=4,*ptr=&a;  //Statement 1

x+=4,y=x*2;  //Statement 2  (Assume x and y are integer variables)

如果是,如何?特别是在第二种情况下,如果逗号不是序列点,我们如何确定在赋值中使用它之前x已经递增了?对于第一条语句,我如何确定在分配地址之前已经初始化并分配了内存?我应该安全地使用以下内容:4y=x*2aptr

int a=4,*ptr;
ptr=&a;

x+=4;
y=x*2;

编辑我对逗号运算符的理解告诉我这些语句是安全的。但是在阅读了关于序列点以及类似的东西printf("%d",a++,++a,a++)是如何未定义的之后,我有了第二个想法。

4

2 回答 2

12

在函数调用中分隔函数参数的逗号不是逗号运算符 - 它只是恰好以与逗号运算符相同的方式拼写的标点符号。不同函数参数的评估之间没有顺序点,所以这就是在这种情况下你得到 UB 的原因。

另一方面,在你的表达中:

x+=4,y=x*2;

这里的逗号逗号操作符,它引入了一个序列点;没有UB。

在声明中,声明符之间的逗号也不是逗号运算符;然而,一个完整的声明符(一个声明符不是另一个声明符的一部分)的结尾确实引入了一个序列点,所以声明如下:

int a = 2, b = a + 1;

不是UB。

于 2013-04-28T13:05:20.997 回答
3

这里没有UB。
根据 C99 标准:

C. 附录 C(资料性):序列点
#1 以下是 5.1.2.3 中描述的序列点:
--在评估参数之后调用函数(6.5.2.2)。
-- 以下运算符的第一个操作数的结尾:逻辑与 && (6.5.13); 逻辑或 || (6.5.14);有条件的?(6.5.15);逗号 , (6.5.17)。

因此,函数调用不涉及逗号运算符。尽管存在逗号。

于 2013-04-28T12:50:30.343 回答