2024年10月18日 11:02

This commit is contained in:
许大仙 2024-10-18 03:02:29 +00:00
parent a777de5bbd
commit d0ed95f44e

View File

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