我对C/C++语言运算规则另类小解

先看看无聊的C运算符优先级和结合性。看到表1的人可以分为三类:

  • C语言编译器的作者
  • 计算机入门者
  • 各种计算机基础能力考试应对者

比如要你计算: -Num++, +Num++, f( a(), b(), c()) ,int a= c,d,e; 之类的运算顺序。

大多数工程师为了避免记忆这繁琐的规则,使用()括号大法来解决大部分运算符优先级/结合性的问题。而且在大多数情况下,商业团队会通过统一的编程规范来避免程序语言的”坑”。

表1:运算符优先级和结合性

优先级 运算符 描述 结合性
1 ++ -- 后缀自增与自减 从左到右
() 函数调用
[] 数组下标
. 结构体与联合体成员访问
-> 结构体与联合体成员通过指针访问
(type){list} 复合字面量(C99)
2 ++ -- 前缀自增与自减[注 1] 从右到左
+ - 一元加与减
! ~ 逻辑非与逐位非
(type) 转型
* 间接(解引用)
& 取址
sizeof 取大小[注 2]
_Alignof 对齐要求(C11)
3 * / % 乘法、除法及余数 从左到右
4 + - 加法及减法
5 << >> 逐位左移及右移
6 < <= 分别为 < 与 ≤ 的关系运算符
> >= 分别为 > 与 ≥ 的关系运算符
7 == != 分别为 = 与 ≠ 关系
8 & 逐位与
9 ^ 逐位异或(排除或)
10 | 逐位或(包含或)
11 && 逻辑与
12 || 逻辑或
13 ?: 三元条件[注 3] 从右到左
14[注 4] = 简单赋值
+= -= 以和及差赋值
*= /= %= 以积、商及余数赋值
<<= >>= 以逐位左移及右移赋值
&= ^= |= 以逐位与、异或及或赋值
15 , 逗号 从左到右

去记忆这种表格明显是反直觉的,我们还是得理解编译器帮我们解释符号的意图。

C的符号可以归结为几类:

  1. 算术运算符。最普通的+ – * / % ~ & | ^ << >>
  2. 逻辑运算符。! && ||
  3. 赋值运算符。= &= <<=
  4. 比较运算符。< == >= <= > !=
  5. 成员访问。 [] () * -> .
  6. 其他 … , (type强转), sizeof, _Alignof

先是结合性,原则很简单,也很人类。

就是按照普通人的阅读顺序去记忆: 比如[], 它肯定是从左到右结合。因为 一个表达式 a[1], 先要知道a,才能知道相对寻址的 a[1]。 再比如算术运算a + b, 肯定是先move a到寄存器,在把a和b想加。因此也是从左向右结合。

那么,哪些是从右往左结合呢?

我们写代码 sizeof( SuperStruct ), 肯定是先想到SuperStruct的大小和地址在哪,然后再去取大小。这就是很直接的计算机思维

最有代表性的是: 前++,前– VS 后++, 后–

用他们来测试下这种规律的正确性:

a++ , 从左到右。因为先得知道a,才能++。

–a , 从右往左结合。 因为先得知道a,才能–。

看,这是不用记忆的。非常直接的计算机符号逻辑

优先级的记忆

优先级最高的: 除了后加/后减的优先级超高。 成员访问优先级高完全符合直觉。成员访问优先级高,可以理解为得先有数据才能做各种运算

优先级次高的: 几乎全部单目运算符优先级是次高的。单目运算符只需要一个操作数,和成员访问有相同的属性。

优先级第三/四高: 接下来是双目运算符, 乘/除/取余(优先级三) 比 加减(优先级四)优先级高,符合直觉。

优先级第五/六高: 算术运算比关系运算优先级高。 加减乘除移位比所有比较符号优先级高。移位这种算术运算 >>, << 比 >,< >=,<= 的符号优先级高。先算出来再比较。

优先级第六/七高: >=, <= 比 ==, !==优先级高。这个没有什么规则。就是C语言编译器的人自己定的规则。 先比较大小,再比较是否相等。

优先级第八/九/⑩高: 位运算自己的比较,依次是 & ^ |

优先级第十一/十二: 逻辑运算 && ||

第十三: 孤零零的一个 三目。

第十四:各种赋值

第十五:孤独的逗号。

所以,总结起来规则是:

  1. 成员运算优先级最高。成员运算符算是单目的一种,所以剩下的单目运算符次高。(单目优先原则,直觉)
  2. 算术运算符比关系比较运算符高。(先算[包括移位]出来再比较,直觉)
  3. 关系比较运算符比位运算符高。(比较完再来做位运算,非直觉)
  4. 位运算比逻辑运算符高。(有运算结果再来做逻辑与或)
  5. 逻辑运算比赋值运算符高。(做完算术,比较,位和逻辑运算再来赋值)
  6. 逗比排在最后。
  7. 结合规则完全从直觉去判断。

我对C/C++语言运算规则另类小解》上有2个想法

  1. 成员单目运算 > 普通单目运算 > 关系运算 > 位运算 > 逻辑运算 > 赋值运算 > 逗号运算。

    结合方向完全用直觉去判断。

  2. 1,先单目取值。
    2,先计算后比较
    3,先比较后做位运算
    4,计算比较结束后,开始逻辑上的关系计算。
    5,最后三目,赋值,逗号。
    6,结合规则按照直觉判断。

发表评论

电子邮件地址不会被公开。 必填项已用*标注