是i = f(); 当f修改i时定义?

Pas*_*uoq 21 c c99 sequence-points

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

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

int f(void) { i++; return 42; }
i = f();
Run Code Online (Sandbox Code Playgroud)

它真的未定义吗?

作为我在我的许多问题中添加的最后一点,我对静态分析的背景感兴趣.我不是自己写的,我只是想知道我是否应该在其他人编写的程序中对此进行警告.

Dav*_*nco 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();
Run Code Online (Sandbox Code Playgroud)

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

  • @James Greenhalgh:什么都没有打破.关于序列点,内联更改绝对没有任何变化."序列点"是一个概念,而不是以某种方式与物理功能体相关联的物理实体.在任何情况下代码都可以,因为每个函数在入口和结尾都有一个序列点,无论它是否内联. (10认同)
  • 那么,如果编译器试图内联这个会发生什么呢?编辑:一切都破了,很高兴知道...... (2认同)

pax*_*blo 8

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

由于您返回42,因此紧跟该return语句后会有一个序列点.

为了完整起见,此处列出了C99序列点,相关的一个加粗:

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


  • 在评估参数之后调用函数(6.5.2.2).
  • 以下运算符的第一个操作数的结尾:logical AND &&(6.5.13); 逻辑OR || (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); 返回语句中的表达式(6.8.6.4).
  • 在库函数返回之前(7.1.4).
  • 在与每个格式化的输入/输出函数转换说明符(7.19.6,7.24.2)相关联的操作之后.
  • 紧接在每次调用比较函数之前和之后,以及对比较函数的任何调用和作为参数传递给该调用的对象的任何移动之间(7.20.5).