运算符优先级及结合顺序随笔
运算符优先级及结合顺序随笔
最近在网上看到一段开源代码中有一个关于链表操作的代码,其中有一行如下:
--pNode->next;
看到这段代码,我一时想不起这些运算符的结合顺序是什么样子了,于是开始查找资料并写了下面的测试程序:
1 // test operator priority 2 typedef struct 3 { 4 int* next; 5 } SturctA; 6 7 int a[] = {0, 1, 2, 3 }; 8 int b = 4; 9 SturctA temp1[2]; 10 SturctA *pTemp1 = &temp1[0]; 11 int val1 = 0, val2 = 0, val3 = 0; 12 13 temp1[0].next = &a[2]; 14 temp1[1].next = &b; 15 16 val1 = *--pTemp1->next; // equals to *(--(pTemp1->next)); after operation val1 = 1, pTemp1 = &temp1[0] 17 NSLog(@"val1 value: %d", val1); 18 19 val2 = *--pTemp1++->next; // equals to *(--(pTemp1->next)), then pTemp1++; after operation val2 = 0, pTemp1 = &temp1[1] 20 NSLog(@"val2 value: %d", val2); 21 22 val3 = *pTemp1->next; 23 NSLog(@"val3 value: %d", val3);
这段代码主要作用是验证前++、--,后++、--,以及->,*的优先级和结合顺序。
程序中第2到5行,首先定义了一个结构体,该结构体中有一个指向int型的指针。第9行定义了一个结构体数组temp1[2],紧接着在第10行定义一个指向结构体数组第0个元素的指针pTemp1。13,14两行分别对数组temp1的两个结构体的next成员变量赋初值。最后16到23行对以上提到的四种的运算符进行了几种组合,并打印测试结果。
下面我们分别看一下几种运算符组合的具体情况:
- 第16行代码,改行包含了前--,->以及*运算符。结合顺序是首先pTemp1->next,然后在对拿到的next进行前--的操作,最后再取出--运算以后的指针所指向的数值。根据分析我们可以得到val1 = 1的结果。
- 第19行代码,在前面执行的基础上(前面的执行已经修改了next指针的指向)进行了前--,后++,->以及*操作。结合顺序是首先pTemp1进行后++的操作(注:后++操作的运算符优先级最高,但不会影响本次执行),然后在和->next结合获得next的值(指向int的指针),接着再对该指针进行前--操作,最后对再取出--运算以后的指针所指向的数值。根据分析我们可以得到val2 = 0的结果(需要考虑到执行完第16行,pTemp1->next已经指向a[1]的地址)。
- 第22行代码,在前面执行的基础上,对pTemp1的后++操作进行了验证,可以明显的看出此时pTemp1已经指向结构体数组的第1个元素了。
上述代码只是为了验证运算符的优先级问题,日常的代码中还是尽量避免这样写,特别是不要想19行那样,建议最好加上“()”,例如19行的代码就可以修改为下面这样:
val2 = *(--((pTemp1++)->next));
总之如果不清楚优先级和结合顺序,就多加一些“()”,这样自己看起来清晰,也方面后面维护代码的同事。
😊请楼主喝杯豆浆😊