【问题标题】:What is the order of excecution of printf(..) parameters? [duplicate]printf(..) 参数的执行顺序是什么? [复制]
【发布时间】:2019-06-30 19:58:27
【问题描述】:

我想做类似printf("%d,%d",array[c], array[c+1]) 的事情,每次迭代中只有一个变量会增加。我写了以下代码,我期望标准输出为“1,2”,我错了:

#include <stdio.h>
int main()
{
    int c = 1;
    printf("%d,%d",c++,c++); /* 2,1 */
    //printf("%d,%d",c,c++);   /* 2,1 */
    //printf("%d,%d",c++,c);   /* 1,2 */
}

如果我尝试执行printf("%d,%d",c++,c)printf("%d,%d",c,c++),我可以看到“c++”语句没有定义的执行顺序。

有人能解释一下我编写的代码是如何编译成的吗?以及它为什么以及如何根据“c++”语句的位置发生变化。

【问题讨论】:

  • 订单未指定。但这也是 c++ 两次没有序列点的未定义行为。

标签: c printf


【解决方案1】:

函数调用中参数的求值顺序未指定, 并且这些表达式的评估之间没有序列点。这意味着 - 如果一个表达式作为副作用改变了一个对象(如 c 的值),该对象也被另一个表达式访问 - 这些表达式的结果将是不可预测的。出于这个原因,该语言将此类情况定义为未定义的行为(例如,参见this 在线 C 标准草案):

6.5 表达式

2.) 如果标量对象的副作用相对于 对同一标量对象或值的不同副作用 使用相同标量对象的值进行计算,行为是 不明确的。 ...

【讨论】:

    【解决方案2】:

    未指定函数参数的求值顺序。由于 ++ 运算符具有副作用 - 在一个表达式(函数调用)中产生两个副作用是未定义的行为。

    【讨论】:

      【解决方案3】:

      C 标准没有定义函数参数的计算顺序。将参数传递到函数的顺序通常由调用约定定义,尽管这仍将评估顺序留给编译器。

      例如,如果您有一个调用约定,其中参数从右到左推入堆栈(这在 x86-32 上很普遍),为 printf("%d %d", c, c++); 生成的程序集可能如下所示:

      push eax ; arg 3
      push edx ; arg 2
      push offset format_string
      call _printf
      add esp, 12
      

      但是,我们仍然无法推断哪个订单 eaxedx 填充了 cc++ 的值。

      【讨论】:

        猜你喜欢
        • 2015-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-14
        • 1970-01-01
        相关资源
        最近更新 更多