许多教材里都没有将这点讲明白:「优先级和运算顺序虽然相关,但并不是谁优先级最高,一定先算谁。」
本文以 C 语言为例。简单阐明一下两者究竟是什么关系。
#include <stdio.h>
int main() {
int a = 1;
int b = 2;
int c = 10;
int d = 100;
int result = a + b + c * d; // result: 1003
return 0;
}
很简单一个程序,然而 a + b + c * d
是如何运算的呢?或者简化一点,谁最先运算?
不妨查看汇编码:
:
project`main0x100003f70 <+0>: pushq %rbp
0x100003f71 <+1>: movq %rsp, %rbp
0x100003f74 <+4>: xorl %eax, %eax
0x100003f76 <+6>: movl $0x0, -0x4(%rbp)
0x100003f7d <+13>: movl $0x1, -0x8(%rbp) // int a = 1
0x100003f84 <+20>: movl $0x2, -0xc(%rbp) // int b = 2
0x100003f8b <+27>: movl $0xa, -0x10(%rbp) // int c = 10
0x100003f92 <+34>: movl $0x64, -0x14(%rbp) // int d = 100
0x100003f99 <+41>: movl -0x8(%rbp), %ecx // 将 a 的值寄存到 ECX
0x100003f9c <+44>: addl -0xc(%rbp), %ecx // ECX += a
0x100003f9f <+47>: movl -0x10(%rbp), %edx // 将 c 的值寄存到 EDX
0x100003fa2 <+50>: imull -0x14(%rbp), %edx // EDX *= d
0x100003fa6 <+54>: addl %edx, %ecx // ECX += EDX
0x100003fa8 <+56>: movl %ecx, -0x18(%rbp) // result = ECX
0x100003fab <+59>: popq %rbp
0x100003fac <+60>: retq
不难发现,最先执行的居然是 a+b
.
这是为何?乘法操作难道不比加法操作优先级更高吗?
的确如此1:
诚然,* 的优先级比 + 高。然而这并不代表,* 一定在 + 之前运算。
这很反直觉对不对?然而无论是先运行 a+b
或是
c*d
对于结果,都是没有影响的。算出来是一样的。
优先级可以这么理解:它决定了该操作在语法树中的层级。
只要层级不乱,先算哪个,全凭编译器的喜好。可以确定,至少
gcc
编译器喜欢先算从左到右,先算 a+b
。