函数调用顺序错误
这就是我今天编写的代码,
#include <iostream>
using namespace std;
int function1()
{
cout<<"hello from function1()"; return 0;
}
int function2()
{
cout<<"hello from function2()"; return 0;
}
int main()
{
int func_diffresult = 0;
func_diffresult = function1() - function2();
cout<<func_diffresult; /** prints 0 correctly **/
}
输出是 get is hello from function2()hello from function1()
。我认为输出应该是 hello from function1()hello from function2()
。我的编译器在玩我吗?
This is what i have coded today
#include <iostream>
using namespace std;
int function1()
{
cout<<"hello from function1()"; return 0;
}
int function2()
{
cout<<"hello from function2()"; return 0;
}
int main()
{
int func_diffresult = 0;
func_diffresult = function1() - function2();
cout<<func_diffresult; /** prints 0 correctly **/
}
the output is get is hello from function2()hello from function1()
. I think the output should be hello from function1()hello from function2()
. Is my compiler playing with me?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
-
运算符的参数求值顺序为 未指定。因此函数可以按任一顺序调用。The order of evaluation of arguments of
-
operator is unspecified. So functions may be called in either order.-
运算符实际上变成了operator-(function1(), function2())
,并且故意未指定函数参数的求值顺序。相关说明:
不指定它的一个很好的理由是为了有效地处理调用约定。例如,C 调用约定要求将参数按相反顺序压入堆栈。
因此,以相反的顺序计算函数是有意义的,因为结果可以立即推送。要从左到右评估参数,然后从右到左推送结果,需要在推送任何结果之前存储所有结果。如果你确实需要这样做,你可以手动完成。如果这对您来说不重要,那么性能优势可能会重要。
The
-
operator effectively becomesoperator-(function1(), function2())
, and the order of evaluation of function parameters is deliberately unspecified.Related notes:
One really good reason to leave it unspecified is to handle calling conventions efficiently. For example, the C calling convention requires parameters be pushed on the stack in reverse order.
Therefore, it makes sense to evaluate the functions in reverse order since the result may be pushed immediately. To evaluate parameters from left-to-right and then push the results from right-to-left involves storing all results before pushing any of them. If you really need to do this, you can do it manually. If it doesn't matter to you, the performance benefit probably does.
ISO 标准不保证子表达式的计算顺序。
来自 c++0x 草案标准:
1.9。程序执行:
:
13/ 之前排序是单个线程执行的评估之间的不对称、传递、成对关系,这会导致这些评估之间存在偏序。给定任意两个评估 A 和 B,如果 A 排序在 B 之前,则 A 的执行应先于 B 的执行。如果 A 未排序在 B 之前且 B 未排序在 A 之前,则 A 和 B 不排序。 [注:未排序的执行
评估可以重叠。]
当 A 在 B 之前排序或 B 在 A 之前排序时,评估 A 和 B 的顺序是不确定的,但未指定是哪一个。 [注意:不确定顺序的评估不能重叠,但可以先执行其中一个。]
:
15/ 除非另有说明,否则各个运算符的操作数和各个表达式的子表达式的求值都是无序的。
:
调用函数时(无论函数是否内联),与任何参数表达式或指定被调用函数的后缀表达式关联的每个值计算和副作用,都会在执行函数体中的每个表达式或语句之前进行排序。调用函数[脚注:换句话说,函数执行不会相互交错]。 [注意:与不同参数表达式相关的值计算和副作用是不排序的。]
调用函数(包括其他函数调用)中的每个计算,如果在被调用函数体执行之前或之后没有以其他方式明确排序,则相对于被调用函数的执行不确定地排序。
换句话说,实现可以使用它想要的任何方法自由地安排调用。然而,根据脚注,函数调用被特殊对待 - 它们不交错。
The ISO standards does not guarantee the order in which subexpressions will be evaluated.
From the c++0x draft standard:
1.9. Program execution:
:
13/ Sequenced before is an asymmetric, transitive, pair-wise relation between evaluations executed by a single thread, which induces a partial order among those evaluations. Given any two evaluations A and B, if A is sequenced before B, then the execution of A shall precede the execution of B. If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced. [Note: The execution of unsequenced
evaluations can overlap.]
Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which. [Note: Indeterminately sequenced evaluations cannot overlap, but either could be executed first.]
:
15/ Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.
:
When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function [Footnote: In other words, function executions do not interleave with each other]. [Note: Value computations and side effects associated with different argument expressions are unsequenced.]
Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.
In other words, the implementation is free to arrange the calls using whatever method it desires. However, function calls are treated specially as per the footnote - they do not interleave.