7
main()
{
    int i=5;
    printf("%d%d%d%d%d%d",i++,i--,++i,--i,i);
}

输出是 45545,但我不知道它是如何工作的。有人说函数调用中的参数是从左到右压入堆栈的。

4

5 回答 5

20

函数参数的评估顺序未指定。

从 c99 标准:

6.5.2.2 函数调用

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

然而,这只是问题的一部分。另一件事(实际上更糟,因为它涉及未定义的行为)是:

6.5 表达式

2/ 在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的评估修改一次。此外,应仅读取先验值以确定要存储的值。

在我们的例子中,所有参数评估仅在 2 个序列点之间:前;一个点和输入函数之前的点,但在所有参数都被评估之后。你最好不要写这样的代码。

C 标准在某些地方相当宽松,为编译器可能进行的优化留出了空间。

于 2012-10-18T17:22:33.677 回答
6

传递给函数的参数的顺序在标准中没有定义,而是由编译器使用的调用约定决定的。我认为在您的情况下,使用cdecl调用约定(许多 C 编译器用于 x86 架构),其中函数中的参数从右到左进行评估。

于 2012-10-18T17:24:55.440 回答
3

此函数调用是未定义的行为:

printf("%d%d%d%d%d%d",i++,i--,++i,--i,i);

在两个序列点之间多次修改对象是 C 中未定义的行为。

这也是未定义的行为,因为您有 6 个转换规范,但格式只有 5 个参数。

于 2012-10-18T17:56:20.263 回答
3

两点:

  • 函数参数以未指定的顺序进行评估。这允许编译器根据自己的喜好进行优化。
  • 您的特定参数会调用未定义的行为。不允许i在序列点之前多次修改。
于 2012-10-18T17:25:37.187 回答
1

参数的评估顺序printf未指定。除其他外,这取决于您使用的系统的调用约定。此外,这也是一种未定义的行为,因为您在i没有任何序列点的情况下进行了多次修改。顺便说一句,缺少一个论点。

于 2012-10-18T17:23:47.380 回答