diff --git a/docs/notes/01_c-basic/05_xdx/index.md b/docs/notes/01_c-basic/05_xdx/index.md index ff3c21c..81af2b9 100644 --- a/docs/notes/01_c-basic/05_xdx/index.md +++ b/docs/notes/01_c-basic/05_xdx/index.md @@ -2361,66 +2361,69 @@ int main() { } ``` -## 2.8 运算符优先级 +## 2.8 运算符优先级和结合性 * 在数学中,如果一个表达式是 `a + b * c` ,我们知道其运算规则就是:先算乘除再算加减。其实,在 C 语言中也是一样的,先算乘法再算加减,即:C 语言中乘除的运算符比加减的运算符的优先级要高。 > [!NOTE] > -> 所谓`优先级`,就是当多个运算符出现在同一个表达式中时,先执行哪个运算符。 +> * ① 所谓的`优先级`:就是当多个运算符出现在同一个表达式中时,先执行哪个运算符。 +> * ② 所谓的`结合性`:就是当多个相同优先级的运算符出现在同一个表达式中的时候,是从左到右运算,还是从右到左运算。 +> * `左结合性`:具有相同优先级的运算符将`从左到右`(➡️)进行计算。 +> * `右结合性`:具有相同优先级的运算符将`从右到左`(⬅️)进行计算。 * C 语言中运算符的优先级有几十个,有的运算符优先级不同,有的运算符优先级相同,如下所示: -| **优先级** | **运算符** | **名称或含义** | **结合方向** | -| ---------- | ---------- | ---------------- | ------------- | -| **1** | `[]` | 数组下标 | ➡️(从左到右) | -| | `()` | 圆括号 | | -| | `.` | 成员选择(对象) | | -| | `->` | 成员选择(指针) | | -| **2** | `-` | 负号运算符 | ⬅️(从右到左) | -| | `(类型)` | 强制类型转换 | | -| | `++` | 自增运算符 | | -| | `--` | 自减运算符 | | -| | `*` | 取值运算符 | | -| | `&` | 取地址运算符 | | -| | `!` | 逻辑非运算符 | | -| | `~` | 按位取反运算符 | | -| | `sizeof` | 长度运算符 | | -| **3** | `/` | 除 | ➡️(从左到右) | -| | `*` | 乘 | | -| | `%` | 余数(取模) | | -| **4** | `+` | 加 | ➡️(从左到右) | -| | `-` | 减 | | -| **5** | `<<` | 左移 | ➡️(从左到右) | -| | `>>` | 右移 | | -| **6** | `>` | 大于 | ➡️(从左到右) | -| | `>=` | 大于等于 | | -| | `<` | 小于 | | -| | `<=` | 小于等于 | | -| **7** | `==` | 等于 | ➡️(从左到右) | -| | `!=` | 不等于 | | -| **8** | `&` | 按位与 | ➡️(从左到右) | -| **9** | `^` | 按位异或 | ➡️(从左到右) | -| **10** | `\|` | 按位或 | ➡️(从左到右) | -| **11** | `&&` | 逻辑与 | ➡️(从左到右) | -| **12** | `\|\|` | 逻辑或 | ➡️(从左到右) | -| **13** | `?:` | 条件运算符 | ⬅️(从右到左) | -| **14** | `=` | 赋值运算符 | ⬅️(从右到左) | -| | `/=` | 除后赋值 | | -| | `*=` | 乘后赋值 | | -| | `%=` | 取模后赋值 | | -| | `+=` | 加后赋值 | | -| | `-=` | 减后赋值 | | -| | `<<=` | 左移后赋值 | | -| | `>>=` | 右移后赋值 | | -| | `&=` | 按位与后赋值 | | -| | `^=` | 按位异或后赋值 | | -| | `\|=` | 按位或后赋值 | | -| **15** | `,` | 逗号运算符 | ➡️(从左到右) | +| 优先级 | 运算符 | 名称或含义 | 结合方向 | +| ------ | ---------- | --------------------------------- | ------------- | +| `0` | `()` | 小括号,最高优先级 | ➡️(从左到右) | +| `1` | `++`、`--` | 后缀自增和自减,如:i++、i-- 等 | ➡️(从左到右) | +| `1` | `()` | 小括号,函数调用,如:sum(1,2) 等 | ➡️(从左到右) | +| `1` | `.` | 成员选择(对象) | ➡️(从左到右) | +| | `->` | 成员选择(指针) | | +| **2** | `-` | 负号运算符 | ⬅️(从右到左) | +| | `(类型)` | 强制类型转换 | | +| | `++` | 自增运算符 | | +| | `--` | 自减运算符 | | +| | `*` | 取值运算符 | | +| | `&` | 取地址运算符 | | +| | `!` | 逻辑非运算符 | | +| | `~` | 按位取反运算符 | | +| | `sizeof` | 长度运算符 | | +| **3** | `/` | 除 | ➡️(从左到右) | +| | `*` | 乘 | | +| | `%` | 余数(取模) | | +| **4** | `+` | 加 | ➡️(从左到右) | +| | `-` | 减 | | +| **5** | `<<` | 左移 | ➡️(从左到右) | +| | `>>` | 右移 | | +| **6** | `>` | 大于 | ➡️(从左到右) | +| | `>=` | 大于等于 | | +| | `<` | 小于 | | +| | `<=` | 小于等于 | | +| **7** | `==` | 等于 | ➡️(从左到右) | +| | `!=` | 不等于 | | +| **8** | `&` | 按位与 | ➡️(从左到右) | +| **9** | `^` | 按位异或 | ➡️(从左到右) | +| **10** | `\|` | 按位或 | ➡️(从左到右) | +| **11** | `&&` | 逻辑与 | ➡️(从左到右) | +| **12** | `\|\|` | 逻辑或 | ➡️(从左到右) | +| **13** | `?:` | 条件运算符 | ⬅️(从右到左) | +| **14** | `=` | 赋值运算符 | ⬅️(从右到左) | +| | `/=` | 除后赋值 | | +| | `*=` | 乘后赋值 | | +| | `%=` | 取模后赋值 | | +| | `+=` | 加后赋值 | | +| | `-=` | 减后赋值 | | +| | `<<=` | 左移后赋值 | | +| | `>>=` | 右移后赋值 | | +| | `&=` | 按位与后赋值 | | +| | `^=` | 按位异或后赋值 | | +| | `\|=` | 按位或后赋值 | | +| **15** | `,` | 逗号运算符 | ➡️(从左到右) | > [!WARNING] > > * ① 不要过多的依赖运算符的优先级来控制表达式的执行顺序,这样可读性太差,尽量`使用小括号来控制`表达式的执行顺序。 > * ② 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它`分成几步`来完成。 > * ③ 运算符优先级不用刻意地去记忆,总体上:一元运算符 > 算术运算符 > 关系运算符 > 逻辑运算符 > 三元运算符 > 赋值运算符。 -