cout vs printf - 执行顺序

时间:2011-09-09 01:54:10

标签: c++ c

  

可能重复:
  Compilers and argument order of evaluation in C++
  cout << order of call to functions it prints?

  1. 此:

    int k=3;
    printf("%d %d %d",k++,k,++k);
    

    输出为4 4 4,因为它们被推入堆栈中:

    %d%d%d
    
    4  -- for k++    
    4  --for k    
    4  --for ++k
    

  2. 此:

    int k = 3;
    cout << k++ << k << ++k;
    

    实际上是重复的函数调用,所以它相当于:

    ( ( (cout << k++) << k) << ++k);
    

    所以,我想首先k++然后k然后++k必须始终按此顺序执行,对吧?我相信函数调用是一个序列点,但输出在不同的实现上有所不同。为什么会这样?

4 个答案:

答案 0 :(得分:7)

标准评估参数的顺序是未指定。这意味着,它可以按照实现的任何顺序发生。

答案 1 :(得分:4)

这是未定义的,因为在printf语句中没有序列点。如果没有序列点,编译器可以按原样顺序写入内存位置k

现在你可能想知道“这到底是什么意思”,为什么它有关系?基本上,序列点是代码中的一个点,其中有问题的内存位置,在这种情况下k最多被修改一次。这里有一个更全面的描述:https://isocpp.org/wiki/faq/misc-technical-issues#double-mod-betw-seq-pt

从FAQ中可以看出,printf中的,没有引入序列点。

cout的情况下,这是不同的,因为对operator >>有3个函数调用。函数调用引入了一个序列点,因此对内存位置k的修改具有已定义的顺序。然而(这是我错过的一点,但Cubbi指出)因为C / C ++没有定义函数参数的评估顺序,即使它们是函数,这些参数也可以按编译器定义的任何顺序进行评估。所以在表达式中:

f(h(), g())

首先评估h()或g()是否未定义:http://www.stroustrup.com/bs_faq2.html#undefined。所以这就是为什么即使在cout的情况下你从不同的编译器得到不同的结果,主要是因为cout << k++ << k << ++k转换为cout.operator<<(k++).operator<<(k).operator(++k)实际上是这样的表达式:f(h(g(cout, k++), k), ++k)和每个函数参数都以未指定的顺序进行评估。

答案 2 :(得分:2)

您的答案涵盖了对printf的调用,但您也在问为什么cout语句的输出在编译器之间有所不同。

你说它等同于

是正确的
( ( (cout<<k++)<<k)<<++k);

现在,要评估该表达式并获得其结果,编译器必须评估最右边的<<。在对<<进行函数调用之前,必须对其两个操作数( (cout<<k++)<<k)++k进行求值。并且这两个评估可以以任何顺序发生,或者甚至同时发生(编译器经常交错来自两个独立的(如编译器认为的)代码分支的cpu指令。 由于对两个表达式的评估都涉及写入k,因此在cout的情况下,行为也是未定义的。

答案 3 :(得分:0)

实际上,printf和cout都是&lt;&lt;是函数调用,C ++和C不定义参数的评估顺序。因此,从编译器到编译器,这些测试用例的结果会有所不同,因为它的实现是定义的。

相关问题