函数调用的序列点?

这是另一个序列点问题,但是一个相当简单的问题:

#include  void f(int p, int) { printf("p: %d\n", p); } int g(int* p) { *p = 42; return 0; } int main() { int p = 0; f(p, g(&p)); return 0; } 

这是未定义的行为吗? 或者对g(&p)的调用是否作为序列点?

不。它不会调用未定义的行为。 它只是未指定 ,因为在标准中未指定评估函数参数的顺序。 因此输出可以是042具体取决于编译器决定的评估顺序。

程序的行为未指定,因为我们不知道函数参数的评估顺序,从草案C ++标准 1.9 程序执行段落3

抽象机器的某些其他方面和操作在本国际标准中描述为未指定的(例如,对函数的参数的评估顺序)。 在可能的情况下,本国际标准定义了一组允许的行为。 […]

在输入函数之前,参数的所有副作用都按照第5.2.2函数调用第8节的顺序排序:

[注意:后缀表达式和参数表达式的评估都是相对于彼此的未经测序的。 在输入函数之前,对参数表达式评估的所有副作用进行排序 (参见1.9)。 – 尾注]

至于C ,第6.5.2.2函数调用第10段中的C99标准草案都涵盖了这两点:

函数指示符的评估顺序,实际参数和实际参数中的子表达式是未指定的,但在实际调用之前有一个序列点。

因此,在CC++中,最终可以得到f(0,0)f(42,0)