作者:解学武

【全网最详细】C语言运算符优先级和结合性速查表(附记忆口诀)

先看一个最简单的例子:int a = 2, b = 3, c = 4;,那么 a + b * c 的结果是多少?小学就学过先乘除后加减,所以先算 b * c = 12,再加 a,结果是 14。C 语言里的大部分运算符也都遵循类似的“谁先算、谁后算”的约定,这个约定就叫优先级。

但 C 语言的运算符远不止加减乘除:全部加起来有 40 个左右,被分成 15 个优先级级别,里面有下标、成员选择、取地址、强制类型转换、位运算、逻辑运算……当它们混在同一个表达式里时,先算谁后算谁,完全由优先级决定;如果优先级相同,再由结合性决定从左往右还是从右往左。这两条规则,加上一个“目”的概念(一个运算符需要几个操作数),就是读懂一切 C 语言表达式的钥匙。

这篇文章把C语言运算符的优先级和结合性一次讲透:
  • 先带你搞懂优先级、结合性、“目”三个基础概念;
  • 再给出一份完整的 15 级速查表,写代码时随时可以查;
  • 最后送上几条好记的记忆口诀。

看完这一篇,再复杂的表达式你也能一眼判断出计算顺序。

不过先把话说在前头:优先级不是用来死记硬背的。写代码时如果对顺序没有十足把握,直接加括号最稳妥,圆括号 ( ) 的优先级最高。

优先级、结合性和目

1)优先级:先算谁,后算谁

所谓优先级,就是当多个运算符出现在同一个表达式中时,决定先执行哪一个。乘法比加法优先、加法又比赋值优先,级别越高越先执行。看个例子:
int a = 16, b = 4, c = 2;
int d = a + b * c;    // 先算 b*c = 8,再算 a + 8 = 24
int e = (a + b) * c;  // 加了括号,先算 a + b = 20,再算 20 * 2 = 40
同样两个表达式,加不加括号结果完全不同,这就是优先级在起作用。而括号的作用就是强行改变默认的计算顺序。

2)结合性:同级运算符谁先算

如果两个运算符优先级相同,又该先算谁呢?这时就要看结合性了。

绝大多数运算符的结合性都是从左往右,比如乘和除同级,a / b * c 先算除法再算乘法:
int a = 16, b = 4, c = 2;
int e = a / b * c;   // 从左往右:先算 16/4 = 4,再算 4*2 = 8
整个 C 语言里,结合方向为从右往左的只有三类:单目运算符、三目运算符、赋值运算符。最典型的是赋值:a = b = c = 100; 是先把 100 赋给 c,再把 c 的值赋给 b,最后赋给 a,一路从右往左“传递”下去。

3)目:一个运算符要几个操作数

“目”可以理解为“眼睛”。一个运算符运算时需要几个数,就叫几目运算符:
  • 单目运算符:只需要一个操作数,比如逻辑非 !a、负号 -a、自增 i++、取地址 &a 等;
  • 双目运算符:需要两个操作数,C 语言里绝大多数运算符都是双目的,比如 a + b、a > b;
  • 三目运算符:需要三个操作数。整个 C 语言只有唯一一个三目运算符,就是条件运算符 a ? b : c。

运算符优先级和结合性速查表

下表按优先级从高到低排列,级别数字越小,优先级越高(1 最高,15 最低)。建议把这张表收藏起来,写代码拿不准的时候回来查一下:

优先级 运算符 名称或含义 使用形式 结合方向 说明
1 [] 数组下标 数组名[常量表达式] 左到右  
1 () 圆括号 / 函数调用 (表达式) / 函数名(形参表) 左到右  
1 . 成员选择(对象) 对象.成员名 左到右  
1 -> 成员选择(指针) 对象指针->成员名 左到右  
2 - 负号运算符 -表达式 右到左 单目运算符
2 (类型) 强制类型转换 (数据类型)表达式 右到左  
2 ++ 自增运算符 ++变量名 / 变量名++ 右到左 单目运算符
2 -- 自减运算符 --变量名 / 变量名-- 右到左 单目运算符
2 * 取值运算符 *指针变量 右到左 单目运算符
2 & 取地址运算符 &变量名 右到左 单目运算符
2 ! 逻辑非运算符 !表达式 右到左 单目运算符
2 ~ 按位取反运算符 ~表达式 右到左 单目运算符
2 sizeof 长度运算符 sizeof(表达式) 右到左  
3 * 表达式 * 表达式 左到右 双目运算符
3 / 表达式 / 表达式 左到右 双目运算符
3 % 余数(取模) 整型表达式 % 整型表达式 左到右 双目运算符
4 + 表达式 + 表达式 左到右 双目运算符
4 - 表达式 - 表达式 左到右 双目运算符
5 << 左移 变量 << 表达式 左到右 双目运算符
5 >> 右移 变量 >> 表达式 左到右 双目运算符
6 > 大于 表达式 > 表达式 左到右 双目运算符
6 >= 大于等于 表达式 >= 表达式 左到右 双目运算符
6 < 小于 表达式 < 表达式 左到右 双目运算符
6 <= 小于等于 表达式 <= 表达式 左到右 双目运算符
7 == 等于 表达式 == 表达式 左到右 双目运算符
7 != 不等于 表达式 != 表达式 左到右 双目运算符
8 & 按位与 表达式 & 表达式 左到右 双目运算符
9 ^ 按位异或 表达式 ^ 表达式 左到右 双目运算符
10 | 按位或 表达式 | 表达式 左到右 双目运算符
11 && 逻辑与 表达式 && 表达式 左到右 双目运算符
12 || 逻辑或 表达式 || 表达式 左到右 双目运算符
13 ?: 条件运算符 表达式1 ? 表达式2 : 表达式3 右到左 三目运算符
14 = 赋值运算符 变量 = 表达式 右到左  
14 += -= *= /= %= 赋值(运算后赋值) 变量 += 表达式 等 右到左  
14 <<= >>= &= ^= |= 赋值(位运算后赋值) 变量 <<= 表达式 等 右到左  
15 , 逗号运算符 表达式, 表达式, … 左到右 优先级最低

上表中可以总结出如下规律:
  1. 结合方向只有三个是从右往左,其余都是从左往右。
  2. 所有双目运算符中只有赋值运算符的结合方向是从右往左。
  3. 另外两个从右往左结合的运算符也很好记,因为它们很特殊:一个是单目运算符,一个是三目运算符。
  4. C语言中有且只有一个三目运算符。
  5. 逗号运算符的优先级最低,要记住。
  6. 此外要记住,对于优先级:算术运算符 > 移位运算符 > 关系运算符 > 逻辑运算符 > 赋值运算符。逻辑运算符中“逻辑非 !”除外。

运算符优先级和结核性记忆口诀

1)按大类记框架

算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 三目运算符 > 赋值运算符 > 逗号运算符(逻辑非 ! 是单目运算符,单独优先计算,不受这个框架约束)

2)记结合方向只看三类

从右往左结合的只有三类:单目运算符、三目运算符、赋值运算符;其余所有运算符全部从左往右结合。

3)万能的保底写法

不确定优先级,就加()圆括号。圆括号优先级最高,想先算哪里就括哪里,既保证结果正确,又让代码一目了然,这本身就是一种良好的编程习惯。

最容易出错的优先级问题(易错点逐个拆解)

优先级同为 1 级的几种运算符如果同时出现,很多初学者会迷糊。下表整理了最高频的 7 个易错情况,每一个都是真实踩过的坑:

优先级问题 表达式 经常误认为的结果 实际结果
. 的优先级高于 *(-> 操作符用于消除这个问题) *p.f p 所指对象的字段 f,等价于:
(*p).f
对 p 取 f 偏移,作为指针,然后进行解除引用操作,等价于:
*(p.f)
[] 高于 * int *ap[] ap 是个指向 int 数组的指针,等价于:
int (*ap)[]
ap 是个元素为 int 指针的数组,等价于:
int *(ap [])
函数 () 高于 * int *fp() fp 是个函数指针,所指函数返回 int,等价于:
int (*fp)()
fp 是个函数,返回 int*,等价于:
int* ( fp() )
== 和 != 高于位操作 (val & mask != 0) (val &mask) != 0 val & (mask != 0)
== 和 != 高于赋值符 c = getchar() != EOF (c = getchar()) != EOF c = (getchar() != EOF)
算术运算符高于位移 运算符 msb << 4 + lsb (msb << 4) + lsb msb << (4 + lsb)
逗号运算符在所有运 算符中优先级最低 i = 1, 2 i = (1,2) (i = 1), 2

这些容易出错的情况,希望读者好好在编译器上调试调试,这样印象会深一些。一定要多调试,光靠看代码,水平是很难提上来的。调试代码才是最长水平的。

总结

运算符优先级和结合性,本质上就是 C 语言为“表达式先算谁后算谁”定下的一套规则:优先级分 15 级,逗号最低、括号最高;同级看结合性,绝大多数从左往右,只有单目、三目、赋值三类从右往左。把“算术 > 关系 > 逻辑 > 赋值 > 逗号”这个大框架和“三个右结合”记在心里,再配合上面的速查表和口诀,日常写代码基本够用了。

最后再强调一遍:这张表不是用来背的,是拿来查的。写代码时遇到没把握的表达式,查表确认,或者干脆多加一对括号,既保证正确又方便别人阅读。用得多了,那些高频的优先级自然就熟了。

声明:当前文章为本站“玩转C语言和数据结构”官方原创,由国家机构和地方版权局所签发的权威证书所保护。

添加微信咨询 加站长微信免费领
C语言学习小册
加站长微信免费领C语言学习小册
微信ID:xiexuewu333