21

相关问题:赋值运算符不是序列点的任何充分理由?

comp.lang.c FAQ我推断下面的程序是未定义的。奇怪的是,它只提到调用f作为一个序列点,在参数的计算和控制转移之间f。从f返回到调用表达式的控制转移未列为序列点。

int f(void) { i++; return 42; }
i = f();

真的是未定义吗?

作为我对许多问题的补充,我在静态分析的背景下对此感兴趣。我不是自己写的,我只是想知道我是否应该在其他人编写的程序中警告它。

4

2 回答 2

9

从 f 返回到调用表达式的控制转移未列为序列点。

是的。

在完整表达式的评估结束时

 

构成表达式语句的完整表达式,或 if、switch、while、for 或 do/while 语句的控制表达式之一,或初始化程序或return 语句中的表达式。

您有一个 return 语句,因此,您有一个序列点。

它甚至没有出现

int f(void) { return i++; } // sequence point here, so I guess we're good
i = f();

未定义。(这对我来说有点奇怪。)

于 2011-05-19T07:28:40.450 回答
8

这根本不是未定义的。C99附录C中列出的序列点之一是完整表达式的结尾,其中一个是return语句中的表达式。

return由于您要返回 42,因此该语句后面紧跟着一个序列点。

为完整起见,此处列出了 C99 序列点,相关的点以粗体显示:

以下是5.1.2.3中描述的顺序点:


  • 在评估参数之后对函数的调用 (6.5.2.2)。
  • 以下运算符的第一个操作数的结尾:逻辑与 && (6.5.13); 逻辑或 || (6.5.14);有条件的?(6.5.15);逗号 , (6.5.17)。
  • 完整声明符的结尾:声明符(6.7.5);
  • 完整表达式的结尾:初始化器(6.7.8);表达式语句中的表达式 (6.8.3);选择语句(if 或 switch)的控制表达式(6.8.4);while 或 do 语句的控制表达式 (6.8.5);for 语句 (6.8.5.3) 的每个表达式;return 语句 (6.8.6.4) 中的表达式
  • 紧接在库函数返回之前 (7.1.4)。
  • 在与每个格式化输入/输出函数转换说明符(7.19.6、7.24.2)关联的操作之后。
  • 在每次调用比较函数之前和之后,以及在对比较函数的任何调用与作为参数传递给该调用的对象的任何移动之间(7.20.5)。
于 2011-05-19T07:25:03.567 回答