[C]表达式结合规律和运算符优先级
表达式结合规律
如果运算符具有相同的优先级(precedence)有些表达式的结合方式是从左往右,有些则是从右往左结合的(例如赋值运算符):
表达式 | 结合律 | 组合方式 |
a/b%c | 从左往右 | (a/b)%c |
a=b=c | 从右往左 | a=(b=c) |
运算符优先级
优先级 | 运算符分类 | 标识符位置 | 运算符 | 表达式实例 | 结合律 |
1 | 前序运算符 | 在运算符前面 | .、->、[]、()、++、--、(类型名){列表} | ptr.m、ptr->m、arr[2]、x++、&(struct Pair){ 1000L, "New York JFK airport" } | 从左往右 |
2 | 一元运算符 | 在运算符后面 | ++、--、!、~、+、-、*、&、sizeof | ++x、!x、*ptr | 从右往左 |
3 | 类型转换运算符 | (类型名称) | (void*)ptr | ||
4 | 乘除法运算 | 在运算符前 | *、/、% | x * y % z | 从左往右 |
5 | 加减法运算 | +、- | x + y | ||
6 | 位移运算符 | <<、>> | x << 6 | ||
7 | 关系运算符 | <、<=、>、>= | x < y | ||
8 | 相等运算符 | ==、!= | x == y | ||
9 | 位运算符AND | & | x & y | ||
10 | 位运算符XOR | ^ | x ^ y | ||
11 | 位运算符OR | | | x | y | ||
12 | 逻辑运算符AND | && | x && y | ||
13 | 逻辑运算符OR | || | x || y | ||
14 | 条件运算符 | N/A | ?: | x?1:2 | 从右往左 |
15 | 赋值运算符 | 在运算符前 | =、+=、-=、*=、/=、%=、&=、^=、|=、<<=、>>= | x += 1 | |
16 | 逗号运算符 | N/A | , | 从左往右 |
除了一元运算符、类型转换运算符、条件运算符、赋值运算符是从右往左结合以外,其他都是从左往右结合的;
例如,*++ptr,等同于*(++ptr),当中括号是没必要的,因为*和前置递增的运算符是同一级别的,并且它的结合律是从右往左;
来看看这个示例:
#include <stdio.h> int arr[] = {7, 8, 9}; int main(void) { int* ptr = arr; int x = 2 * *++ptr; printf("%d\n", x); return 0; }
尝试先自己算算x得出的什么结果;
表达式(2 * *++ptr)中,由于间接运算符比乘法运算符优先级要高,所以它会先执行间接运算符;
但是由于间接运算符后面还接前置递增号,因为两者的优先级是一样的,所以结合律起作用了;
子表达式(*++ptr)从右往左运算,得出的值是arr元素8;
再运行2 * 8,结果是16;
你算对了吗?