服务端视角的C++从入门到精通(十四)

116 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第23天,点击查看活动详情

想在这里分享一些不太容易被开发者注意的细节,或者说是陷阱、坑。

移位运算符<<和加减运算符+/-的优先级问题

#include <cstdio>
void testOperatorPriority()
{
	int a = 1, b = 2;
	printf("a+b+1<<1=%d\n", a + b + 1 << 1);
	printf("(a+b+1)<<1=%d\n", (a + b + 1) << 1);
}
int main(){
    testOperatorPriority();
    
    return 0;
}

上面这两种写法得到的输出都是8,但是,看下面这个例子:

#include <cstdio>
#include <iostream>
using namespace std;
int main(){
    printf("%d\n",1<<2 -1);
    cout << 1<<2-1 << endl;
    
    return 0;
}

上面这是C/C++版的代码,下面这是Golang版的代码。

package main

import "fmt"

func main() {
	fmt.Println(1 << 2-1)
}

实际上,C/C++版的代码会分别输出211,而Golang版则会输出3

这里就是本篇文章要讨论的重点。

对于C语言版printf函数输出的结果,其中+运算符的优先级要高于<<,所以,先算21=12-1=1,然后再算1<<1,得到结果2。而对于下面C++版cout函数输出的结果,其实并非11这个数字,而是两个1,原因也很简单,就是因为cout也重载了<<运算符,所以这里的<<其实就被重载掉了、失去了它原本的移位意义,而-的优先级是比<<高的(和上面说的一致,因为+/-优先级相同),所以输出部分自然而然地被分割为了两份,一份是1,另一份是21=12-1=1

对于Golang版Println函数输出的结果,其实正好和C语言版相反:Golang中的<<运算符优先级是比-要高的,所以先算1<<2得到4,然后再计算41=34-1=3,最后输出3。

这也就告诫我们,对于运算符优先级,首先是不能想当然,不可以按照以往的固有经验来进行判定,不同语言之间可能是不通的(当然绝大部分标准是保持一致的),更不可以按照谁和谁挨得近来判定(这是最不靠谱的了,除了在类似于Python这种依靠缩进来控制代码块的语言外,绝大部分语言的空格只是为了美观,也就是绝不包含,或者说不应当包含任何语义暗示)!最好的办法还是在拿不准的时候自己动手写个小例子试一下,不过这其实要求也蛮高了,大部分人可能还是处于自己不知道自己不知道的水平。:)