cout vs printf – 执行顺序

可能重复:
C ++中编译器和评估的参数顺序
cout <<打印函数的调用顺序?

  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必须始终按此顺序执行,对吧? 我相信函数调用是一个序列点,但输出在不同的实现上有所不同。 为什么会这样?

这是未定义的,因为在printf语句中没有序列点。 如果没有序列点,编译器可以自由地按顺序对存储器位置k进行排序。

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

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

cout的情况下,这是不同的,因为有3个函数调用operator >> 。 函数调用引入序列点,因此对存储器位置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)并且每个函数参数以未指定的顺序计算。

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

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

你说它等同于你是对的

 ( ( (cout< 

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

实际上,printf和cout <<都是函数调用,而C ++和C都没有定义参数的评估顺序。 因此,这些测试用例的结果因编译器而异,因为它的实现已定义。