微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C带有嵌入式功能调用的输出评估顺序

我是一个介绍C类的TA.以上问题是在上个星期进行的测试中提出的:

以下程序的输出是什么?

int myFunc(int &x) {
   int temp = x * x * x;
   x += 1;
   return temp;
}

int main() {
   int x = 2;
   cout << myFunc(x) << endl << myFunc(x) << endl << myFunc(x) << endl;
}

对我和所有同事的回答显然是:

8
27
64

但现在有几个学生已经指出,当他们在某些环境下运行时,他们实际上是相反的:

64
27
8

当我使用gcc在我的linux环境中运行它,我会得到我的期望.在我的Windows机器上使用MinGW,我得到他们在说什么.
它似乎在评估最后一次调用myFunc,然后是第二次调用,然后是第一次,然后一旦它有所有的结果,它以正常的顺序输出它们,从第一个开始.但是因为电话是按顺序排列的,所以数字是相反的.

在我看来,作为一个编译器优化,选择以相反的顺序来评估函数调用,但是我不知道为什么.我的问题是:我的假设是否正确?这是背景中发生了什么吗?还是有完全不同的东西?此外,我不明白为什么会有一个好处来评估功能,然后评估输出向前.由于ostream的工作方式,产出必须向前推进,但似乎对功能的评估也应该是前进的.

谢谢你的帮助!

解决方法

C标准没有定义对表达式的子表达式进行评估的顺序,除了引入顺序的某些操作符(逗号运算符,三元运算符,短路逻辑运算符)以及组成函数/运算符的参数/操作数都在函数/运算符本身之前进行评估.

海湾合作委员会没有义务向你(或我)解释为什么要按照这样的方式订购.这可能是一个性能优化,这可能是因为编译器代码出现了更短和更简单的几行,这可能是因为其中一个mingw编程人员亲自憎恨你,并希望确保如果你做出假设,标准保证,您的代码出错.欢迎来到开放标准的世界:-)

编辑添加:litb在下面描述(un)定义的行为.该标准表示,如果您在表达式中多次修改变量,并且如果存在该表达式的有效的评估顺序,以使变量多次修改,而其间没有序列点,则该表达式具有未定义的行为.这在这里不适用,因为变量在调用函数时被修改,并且在任何函数调用的开始都有一个序列点(即使编译器内联它).但是,如果您手动内嵌代码

std::cout << pow(x++,3) << endl << pow(x++,3) << endl;

那么这将是未定义的行为.在这代码中,编译器对所有三个“x”子表达式进行求值,然后对pow进行三次调用,然后开始对运算符<<<因为这个顺序是有效的,没有分离x的修改的顺序点,结果是完全未定义的.在你的代码片段中,只有执行顺序是未指定的.

原文地址:https://www.jb51.cc/c/113262.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐