函数调用的序列点

Sequence point from function call?

本文关键字:函数调用      更新时间:2023-10-16

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

#include <stdio.h>
void f(int p, int) {
  printf("p: %dn", 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,这两点都包含在C99标准草案的6.5.2.2部分中。函数调用第10段

函数指示符的求值顺序、实际参数以及实际参数中的子表达式未指定,但有一个序列点在实际呼叫之前。

因此,在CC++中,您可以使用f(0,0)f(42,0)