c00*_*0fd 0 c++ gcc operator-precedence visual-studio-2017
比如说,在下面的测试表达式中:
int ggg9 = fggg2() + (fggg3() && fggg4() < fggg5() * fggg6());
// 4 11 6 3
Run Code Online (Sandbox Code Playgroud)
如果我们遵循运算符优先级(在表达式下面的注释行中显示),我会假设首先计算parens中的表达式,然后将结果添加到fggg2().
因此,我假设它将按此顺序解决:
int r1 = fggg5() * fggg6(); //Precedence 3 (inside parens)
int r2 = fggg4() < r1; //Precedence 6 (inside parens)
int r3 = fggg3() && r2; //Precedence 11 (inside parens)
int ggg9 = fggg2() + r3; //Outside of parens, so it's last
Run Code Online (Sandbox Code Playgroud)
但是x86-64 gcc 8.2 解决它是这样的:
(我将它转换回C++)
int i0;
int r2 = fggg2();
int r3 = fggg3();
if(!r3) goto L13;
int r4 = fggg4();
int r5 = fggg5();
int r6 = fggg6();
int i1 = r5 * r6;
if(r4 >= i1) goto L13
i0 = 1;
goto L14
L13:
i0 = 0;
L14:
int ggg9 = i0 + r2;
Run Code Online (Sandbox Code Playgroud)
那么,为什么&&运营商似乎之前进行评估*,然后<当他们的优先级为11,3,6,分别?
最后,为什么通过fggg2()首先评估它似乎并不关心parens ?VS2017似乎最后一次评估它.
从我看来,gcc编译器只是从左到右评估所有这些函数,而不考虑优先级.
您将优先级与评估顺序混为一谈.
这是一个非常常见的混乱.也许是因为英语中的"先行"这个词可以有时间含义.但实际上它意味着排名层次结构(例如这里).
在更简单的表达式中a() + b() * c(),优先级告诉我们运算*符的操作数是b()和c(),以及+are 的操作数a()和乘法的结果.没有更多,也没有更少.
这些函数a,b,c可能仍以任何顺序调用.
这是事实,该值计算的*,必须在之前完成值计算的+,因为我们需要知道前者的结果,以计算后者.
值计算是评估操作数的不同步骤.必须在计算值之前评估运算符的操作数,但没有比这更严格的要求.关于评估操作数的部分排序没有规则.
即使右操作数由许多子表达式组成,+也可以在右操作数之前计算左操作数+.编译器可能会评估所有"叶子"操作数,将结果存储在堆栈中,然后执行值计算.
不一定存在严格的值计算顺序,例如w() * x() + y() * z(),两个值计算*可以以任一顺序发生.
在您的代码中,&&操作员确实有一个特殊的排序限制(有时称为短路).必须在开始评估右操作数之前评估左操作数.
将优先告诉我们的左操作数&&是fgg3(),和右边的操作数&&是fggg4() < fggg5() * fggg6()).因此,要求fgg3()在任何之前调用fgg4,fgg5并且fgg6.在您的示例中,对操作数的评估顺序没有其他限制.在fgg2可能发生在任何时间,4,5,6可以以任意顺序,只要他们毕竟是3.
| 归档时间: |
|
| 查看次数: |
129 次 |
| 最近记录: |