707 lines
23 KiB
Markdown
Raw Normal View History

2024-10-22 11:18:31 +08:00
# 第一章:前言
2024-10-18 08:21:00 +00:00
2024-10-22 02:47:49 +00:00
## 1.1 运算符、表达式和操作数
2024-10-18 08:21:00 +00:00
2024-10-22 02:47:49 +00:00
* 运算符是一种特殊的符号,用于数据的运算、赋值和比较等。
* `表达式`指的是一组运算数、运算符的组合,表达式`一定具有值`,一个变量或一个常量可以是表达式,变量、常量和运算符也可以组成表达式,如:
2024-10-18 08:21:00 +00:00
2024-10-22 02:47:49 +00:00
![](./assets/20.svg)
2024-10-18 08:21:00 +00:00
2024-10-22 02:47:49 +00:00
* `操作数`指的是`参与运算``值`或者`对象`,如:
2024-10-18 08:21:00 +00:00
2024-10-22 02:47:49 +00:00
![](./assets/21.svg)
2024-10-18 08:21:00 +00:00
2024-10-22 02:47:49 +00:00
## 1.2 运算符的分类
2024-10-18 08:21:00 +00:00
2024-10-22 02:47:49 +00:00
* 根据`操作数``个数`,可以将运算符分为:
* 一元运算符(一目运算符)。
* 二元运算符(二目运算符)。
* 三元运算符(三目运算符)。
* 根据`功能`,可以将运算符分为:
* 算术运算符。
* 关系运算符(比较运算符)。
* 逻辑运算符。
* 赋值运算符。
* 逻辑运算符。
* 位运算符。
* 三元运算符。
2024-10-18 08:21:00 +00:00
> [!NOTE]
>
2024-10-22 02:47:49 +00:00
> 掌握一个运算符,需要关注以下几个方面:
2024-10-18 08:21:00 +00:00
>
2024-10-22 02:47:49 +00:00
> * ① 运算符的含义。
> * ② 运算符操作数的个数。
> * ③ 运算符所组成的表达式。
> * ④ 运算符有无副作用,即:运算后是否会修改操作数的值。
2024-10-18 08:21:00 +00:00
2024-10-22 02:49:47 +00:00
# 第二章:算术运算符(⭐)
2024-10-18 08:21:00 +00:00
2024-10-22 02:47:49 +00:00
## 2.1 概述
2024-10-18 08:21:00 +00:00
2024-10-22 02:47:49 +00:00
* 算术运算符是对数值类型的变量进行运算的,如下所示:
2024-10-18 08:21:00 +00:00
2024-10-22 02:47:49 +00:00
| 运算符 | 描述 | 操作数个数 | 组成的表达式的值 | 副作用 |
| ------ | ------------ | ---------- | ------------------------ | ------ |
| `+` | 正号 | 1 | 操作数本身 | ❎ |
| `-` | 负号 | 1 | 操作数符号取反 | ❎ |
| `+` | 加号 | 2 | 两个操作数之和 | ❎ |
| `-` | 减号 | 2 | 两个操作数之差 | ❎ |
| `*` | 乘号 | 2 | 两个操作数之积 | ❎ |
| `/` | 除号 | 2 | 两个操作数之商 | ❎ |
| `%` | 取模(取余) | 2 | 两个操作数相除的余数 | ❎ |
| `++` | 自增 | 1 | 操作数自增前或自增后的值 | ✅ |
| `--` | 自减 | 1 | 操作数自减前或自减后的值 | ✅ |
2024-10-18 08:21:00 +00:00
> [!NOTE]
>
2024-10-22 02:47:49 +00:00
> 自增和自减:
2024-10-18 08:21:00 +00:00
>
2024-10-22 02:47:49 +00:00
> * ① 自增、自减运算符可以写在操作数的前面也可以写在操作数后面,不论前面还是后面,对操作数的副作用是一致的。
> * ② 自增、自减运算符在前在后,对于表达式的值是不同的。 如果运算符在前,表达式的值是操作数自增、自减之后的值;如果运算符在后,表达式的值是操作数自增、自减之前的值。
> * ③ `变量前++`:变量先自增 1 ,然后再运算;`变量后++`:变量先运算,然后再自增 1 。
> * ④ `变量前--`:变量先自减 1 ,然后再运算;`变量后--`:变量先运算,然后再自减 1 。
> * ⑤ 对于 `i++` 或 `i--` 各种编程语言的用法和支持是不同的例如C/C++、Java 等完全支持Python 压根一点都不支持Go 语言虽然支持 `i++` 或 `i--` ,却只支持这些操作符作为独立的语句,并且不能嵌入在其它的表达式中。
2024-10-18 17:40:18 +08:00
2024-10-22 02:47:49 +00:00
## 2.2 应用示例
2024-10-18 17:40:18 +08:00
2024-10-22 02:47:49 +00:00
* 示例:正号和负号
2024-10-18 17:40:18 +08:00
2024-10-22 02:47:49 +00:00
```c
#include <stdio.h>
2024-10-18 17:40:18 +08:00
2024-10-22 02:47:49 +00:00
int main() {
2024-10-18 17:40:18 +08:00
2024-10-22 02:47:49 +00:00
int x = 12;
int x1 = -x, x2 = +x;
2024-10-18 17:40:18 +08:00
2024-10-22 02:47:49 +00:00
int y = -67;
int y1 = -y, y2 = +y;
2024-10-21 02:52:59 +00:00
2024-10-22 02:47:49 +00:00
printf("x1=%d, x2=%d \n", x1, x2); // x1=-12, x2=12
printf("y1=%d, y2=%d \n", y1, y2); // y1=67, y2=-67
2024-10-21 02:52:59 +00:00
2024-10-22 02:47:49 +00:00
return 0;
}
```
2024-10-21 02:52:59 +00:00
2024-10-22 02:47:49 +00:00
* 示例:加、减、乘、除(整数之间做除法时,结果只保留整数部分而舍弃小数部分)、取模
2024-10-18 17:40:18 +08:00
2024-10-22 02:47:49 +00:00
```c
#include <stdio.h>
2024-10-21 02:52:59 +00:00
2024-10-22 02:47:49 +00:00
int main() {
2024-10-21 11:06:11 +08:00
2024-10-22 02:47:49 +00:00
int a = 5;
int b = 2;
2024-10-21 06:20:38 +00:00
2024-10-22 02:47:49 +00:00
printf("%d + %d = %d\n", a, b, a + b); // 5 + 2 = 7
printf("%d - %d = %d\n", a, b, a - b); // 5 - 2 = 3
printf("%d × %d = %d\n", a, b, a * b); // 5 × 2 = 10
printf("%d / %d = %d\n", a, b, a / b); // 5 / 2 = 2
printf("%d %% %d = %d\n", a, b, a % b); // 5 % 2 = 1
2024-10-21 06:20:38 +00:00
2024-10-22 02:47:49 +00:00
return 0;
}
```
2024-10-21 13:55:15 +08:00
2024-10-22 02:47:49 +00:00
* 示例:取模(运算结果的符号与被模数也就是第一个操作数相同。)
2024-10-21 13:55:15 +08:00
2024-10-22 02:47:49 +00:00
```c
#include <stdio.h>
2024-10-21 13:55:15 +08:00
2024-10-22 02:47:49 +00:00
int main() {
2024-10-21 13:55:15 +08:00
2024-10-22 02:47:49 +00:00
int res1 = 10 % 3;
printf("10 %% 3 = %d\n", res1); // 10 % 3 = 1
2024-10-21 13:55:15 +08:00
2024-10-22 02:47:49 +00:00
int res2 = -10 % 3;
printf("-10 %% 3 = %d\n", res2); // -10 % 3 = -1
2024-10-21 13:55:15 +08:00
2024-10-22 02:47:49 +00:00
int res3 = 10 % -3;
printf("10 %% -3 = %d\n", res3); // 10 % -3 = 1
2024-10-21 13:55:15 +08:00
2024-10-22 02:47:49 +00:00
int res4 = -10 % -3;
printf("-10 %% -3 = %d\n", res4); // -10 % -3 = -1
2024-10-21 13:55:15 +08:00
return 0;
}
```
2024-10-22 02:47:49 +00:00
* 示例:自增和自减
2024-10-21 13:55:15 +08:00
2024-10-22 02:47:49 +00:00
```c
#include <stdio.h>
2024-10-21 13:55:15 +08:00
2024-10-22 02:47:49 +00:00
int main() {
2024-10-21 13:55:15 +08:00
2024-10-22 02:47:49 +00:00
int i1 = 10, i2 = 20;
int i = i1++;
printf("i = %d\n", i); // i = 10
printf("i1 = %d\n", i1); // i1 = 11
2024-10-21 13:55:15 +08:00
2024-10-22 02:47:49 +00:00
i = ++i1;
printf("i = %d\n", i); // i = 12
printf("i1 = %d\n", i1); // i1 = 12
2024-10-21 13:55:15 +08:00
2024-10-22 02:47:49 +00:00
i = i2--;
printf("i = %d\n", i); // i = 20
printf("i2 = %d\n", i2); // i2 = 19
2024-10-21 13:55:15 +08:00
2024-10-22 02:47:49 +00:00
i = --i2;
printf("i = %d\n", i); // i = 18
printf("i2 = %d\n", i2); // i2 = 18
2024-10-21 07:28:36 +00:00
2024-10-22 02:47:49 +00:00
return 0;
2024-10-21 08:56:58 +00:00
```
* 示例:
```c
#include <stdio.h>
2024-10-22 02:47:49 +00:00
/*
随意给出一个整数,打印显示它的个位数,十位数,百位数的值。
格式如下:
数字xxx的情况如下
个位数:
十位数:
百位数:
例如:
数字153的情况如下
个位数3
十位数5
百位数1
*/
2024-10-21 08:56:58 +00:00
int main() {
2024-10-22 02:47:49 +00:00
int num = 153;
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
int bai = num / 100;
int shi = num % 100 / 10;
int ge = num % 10;
printf("百位为:%d \n", bai);
printf("十位为:%d \n", shi);
printf("个位为:%d \n", ge);
2024-10-21 08:56:58 +00:00
return 0;
}
```
2024-10-22 02:49:47 +00:00
# 第三章:关系运算符(⭐)
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
## 3.1 概述
2024-10-22 02:49:47 +00:00
* 常见的关系运算符(比较运算符),如下所示:
2024-10-22 02:47:49 +00:00
| 运算符 | 描述 | 操作数个数 | 组成的表达式的值 | 副作用 |
| ------ | -------- | ---------- | ---------------- | ------ |
| `==` | 相等 | 2 | 0 或 1 | ❎ |
| `!=` | 不相等 | 2 | 0 或 1 | ❎ |
| `<` | 小于 | 2 | 0 或 1 | ❎ |
| `>` | 大于 | 2 | 0 或 1 | ❎ |
| `<=` | 小于等于 | 2 | 0 或 1 | ❎ |
| `>=` | 大于等于 | 2 | 0 或 1 | ❎ |
2024-10-21 08:56:58 +00:00
> [!NOTE]
>
2024-10-22 02:47:49 +00:00
> * ① C 语言中,没有严格意义上的布尔类型,可以使用 0 或 1表示布尔类型的值。
> * ② 不要将 `==` 写成 `=``==` 是比较运算符,而 `=` 是赋值运算符。
> * ③ `>=` 或 `<=`含义是只需要满足 `大于或等于`、`小于或等于`其中一个条件,结果就返回真。
2024-10-21 08:56:58 +00:00
2024-10-22 11:21:30 +08:00
## 3.2 应用示例
2024-10-21 08:56:58 +00:00
* 示例:
```c
#include <stdio.h>
int main() {
2024-10-22 02:47:49 +00:00
int a = 8;
int b = 7;
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
printf("a > b 的结果是:%d \n", a > b); // a > b 的结果是1
printf("a >= b 的结果是:%d \n", a >= b); // a >= b 的结果是1
printf("a < b 的结果是%d \n", a < b); // a < b 的结果是0
printf("a <= b 的结果是:%d \n", a <= b); // a <= b 的结果是0
printf("a == b 的结果是:%d \n", a == b); // a == b 的结果是0
printf("a != b 的结果是:%d \n", a != b); // a != b 的结果是1
2024-10-21 08:56:58 +00:00
return 0;
}
```
2024-10-22 02:49:47 +00:00
# 第四章:逻辑运算符(⭐)
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
## 4.1 概述
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
* 常见的逻辑运算符,如下所示:
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
| 运算符 | 描述 | 操作数个数 | 组成的表达式的值 | 副作用 |
| ------ | ------ | ---------- | ---------------- | ------ |
| `&&` | 逻辑与 | 2 | 0 或 1 | ❎ |
| `\|\|` | 逻辑或 | 2 | 0 或 1 | ❎ |
| `!` | 逻辑非 | 2 | 0 或 1 | ❎ |
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
* 逻辑运算符提供逻辑判断功能,用于构建更复杂的表达式,如下所示:
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
| a | b | a && b | a \|\| b | !a |
| ------- | ------- | ------- | -------- | ------- |
| 1 | 1 | 1 | 1 | 0 |
| 1 | 0 | 0 | 1 | 0 |
| 0 | 1 | 0 | 1 | 1 |
| 0 | 0 | 0 | 0 | 1 |
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
> [!NOTE]
>
> * ① 对于逻辑运算符来说,任何`非零值`都表示`真``零值`表示`假`,如:`5 || 0` 返回 `1` `5 && 0` 返回 `0` 。
> * ② 逻辑运算符的理解:
> * `&&` 的理解就是:`两边条件,同时满足`。
> * `||`的理解就是:`两边条件,二选一`。
> * `!` 的理解就是:`条件取反`。
> * ③ 短路现象:
> * 对于 `a && b` 操作来说,当 a 为假(或 0 )时,因为 `a && b` 结果必定为 0所以不再执行表达式 b。
> * 对于 `a || b` 操作来说,当 a 为真(或非 0 )时,因为 `a || b` 结果必定为 1所以不再执行表达式 b。
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
## 4.2 应用示例
2024-10-21 08:56:58 +00:00
* 示例:
2024-10-22 02:47:49 +00:00
```c
2024-10-21 08:56:58 +00:00
#include <stdio.h>
int main() {
2024-10-22 02:47:49 +00:00
int a = 0;
int b = 0;
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
printf("请输入整数a的值");
scanf("%d", &a);
printf("请输入整数b的值");
scanf("%d", &b);
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
if (a > b) {
printf("%d > %d", a, b);
} else if (a < b) {
printf("%d < %d", a, b);
} else {
printf("%d = %d", a, b);
}
2024-10-21 08:56:58 +00:00
return 0;
}
```
* 示例:
2024-10-22 02:47:49 +00:00
```c
2024-10-21 08:56:58 +00:00
#include <stdio.h>
2024-10-22 02:47:49 +00:00
// 短路现象
2024-10-21 08:56:58 +00:00
int main() {
2024-10-22 02:47:49 +00:00
int i = 0;
int j = 10;
if (i && j++ > 0) {
printf("床前明月光\n"); // 这行代码不会执行
} else {
printf("我叫郭德纲\n");
}
printf("%d \n", j); //10
2024-10-21 08:56:58 +00:00
return 0;
}
```
2024-10-21 13:55:15 +08:00
2024-10-21 08:56:58 +00:00
* 示例:
2024-10-22 02:47:49 +00:00
```c
2024-10-21 08:56:58 +00:00
#include <stdio.h>
2024-10-22 02:47:49 +00:00
// 短路现象
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
int main() {
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
int i = 1;
int j = 10;
if (i || j++ > 0) {
printf("床前明月光 \n");
} else {
printf("我叫郭德纲 \n"); // 这行代码不会被执行
}
printf("%d\n", j); //10
2024-10-21 08:56:58 +00:00
return 0;
}
```
2024-10-22 02:49:47 +00:00
# 第五章:赋值运算符(⭐)
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
## 5.1 概述
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
* 常见的赋值运算符,如下所示:
| 运算符 | 描述 | 操作数个数 | 组成的表达式的值 | 副作用 |
| ------ | ------------ | ---------- | ---------------- | ------ |
| `==` | 赋值 | 2 | 左边操作数的值 | ✅ |
| `+=` | 相加赋值 | 2 | 左边操作数的值 | ✅ |
| `-=` | 相减赋值 | 2 | 左边操作数的值 | ✅ |
| `*=` | 相乘赋值 | 2 | 左边操作数的值 | ✅ |
| `/=` | 相除赋值 | 2 | 左边操作数的值 | ✅ |
| `%=` | 取余赋值 | 2 | 左边操作数的值 | ✅ |
| `<<=` | 左移赋值 | 2 | 左边操作数的值 | ✅ |
| `>>=` | 右移赋值 | 2 | 左边操作数的值 | ✅ |
| `&=` | 按位与赋值 | 2 | 左边操作数的值 | ✅ |
| `^=` | 按位异或赋值 | 2 | 左边操作数的值 | ✅ |
| `\|=` | 按位或赋值 | 2 | 左边操作数的值 | ✅ |
2024-10-21 08:56:58 +00:00
> [!NOTE]
>
2024-10-22 02:47:49 +00:00
> * ① 赋值运算符的第一个操作数(左值)必须是变量的形式,第二个操作数可以是任何形式的表达式。
> * ② 赋值运算符的副作用针对第一个操作数。
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
## 5.2 应用示例
2024-10-21 08:56:58 +00:00
* 示例:
2024-10-22 02:47:49 +00:00
```c
2024-10-21 08:56:58 +00:00
#include <stdio.h>
int main() {
2024-10-22 02:47:49 +00:00
int a = 3;
a += 3; // a = a + 3
printf("a = %d\n", a); // a = 6
int b = 3;
b -= 3; // b = b - 3
printf("b = %d\n", b); // b = 0
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
int c = 3;
c *= 3; // c = c * 3
printf("c = %d\n", c); // c = 9
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
int d = 3;
d /= 3; // d = d / 3
printf("d = %d\n", d); // d = 1
int e = 3;
e %= 3; // e = e % 3
printf("e = %d\n", e); // e = 0
2024-10-21 08:56:58 +00:00
return 0;
}
```
2024-10-22 02:47:49 +00:00
# 第六章:位运算符(了解)
## 6.1 概述
* C 语言提供了一些位运算符能够让我们操作二进制位bit
* 常见的位运算符,如下所示。
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
| 运算符 | 描述 | 操作数个数 | 运算规则 | 副作用 |
| ------ | ---------- | ---------- | ------------------------------------------------------------ | ------ |
| `&` | 按位与 | 2 | 两个二进制位都为 1 ,结果为 1 ,否则为 0 。 | ❎ |
| `\|` | 按位或 | 2 | 两个二进制位只要有一个为 1包含两个都为 1 的情况),结果为 1 ,否则为 0 。 | ❎ |
| `^` | 按位异或 | 2 | 两个二进制位一个为 0 ,一个为 1 ,结果为 1否则为 0 。 | ❎ |
| `~` | 按位取反 | 2 | 将每一个二进制位变成相反值,即 0 变成 1 1 变 成 0 。 | ❎ |
| `<<` | 二进制左移 | 2 | 将一个数的各二进制位全部左移指定的位数,左 边的二进制位丢弃,右边补 0。 | ❎ |
| `>>` | 二进制右移 | 2 | 将一个数的各二进制位全部右移指定的位数,正数左补 0负数左补 1右边丢弃。 | ❎ |
2024-10-21 08:56:58 +00:00
> [!NOTE]
>
2024-10-22 02:47:49 +00:00
> 操作数在进行位运算的时候,以它的补码形式计算!!!
## 6.2 输出二进制位
* 在 C 语言中,`printf` 是没有提供输出二进制位的格式占位符的;但是,我们可以手动实现,以方便后期操作。
2024-10-21 08:56:58 +00:00
* 示例:
```c
#include <stdio.h>
2024-10-22 02:47:49 +00:00
/**
* 获取指定整数的二进制表示
* @param num 整数
* @return 二进制表示的字符串,不包括前导的 '0b' 字符
*/
char* getBinary(int num) {
static char binaryString[33];
int i, j;
for (i = sizeof(num) * 8 - 1, j = 0; i >= 0; i--, j++) {
const int bit = (num >> i) & 1;
binaryString[j] = bit + '0';
}
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
binaryString[j] = '\0';
return binaryString;
}
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
int main() {
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
int a = 17;
int b = -12;
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
printf("整数 %d 的二进制表示:%s \n", a, getBinary(a));
printf("整数 %d 的二进制表示:%s \n", b, getBinary(b));
2024-10-21 08:56:58 +00:00
return 0;
}
```
2024-10-21 13:55:15 +08:00
2024-10-22 02:47:49 +00:00
## 6.3 按位与
2024-10-21 13:55:15 +08:00
2024-10-22 02:47:49 +00:00
* 按位与 `&` 的运算规则是:如果二进制对应的位上都是 1 才是 1 ,否则为 0 ,即:
* `1 & 1` 的结果是 `1`
* `1 & 0` 的结果是 `0`
* `0 & 1` 的结果是 `0`
* `0 & 0` 的结果是 `0`
2024-10-21 13:55:15 +08:00
2024-10-21 07:28:36 +00:00
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
* 示例:`9 & 7 = 1`
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
![](./assets/22.svg)
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
* 示例:`-9 & 7 = 7`
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
![](./assets/23.svg)
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
## 6.4 按位或
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
* 按位与 `|` 的运算规则是:如果二进制对应的位上只要有 1 就是 1 ,否则为 0 ,即:
* `1 | 1` 的结果是 `1`
* `1 | 0` 的结果是 `1`
* `0 | 1` 的结果是 `1`
* `0 | 0` 的结果是 `0`
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
* 示例:`9 | 7 = 15`
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
![](./assets/24.svg)
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
* 示例:`-9 | 7 = -9`
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
![](./assets/25.svg)
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
## 6.5 按位异或
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
* 按位与 `^` 的运算规则是:如果二进制对应的位上一个为 1 一个为 0 就为 1 ,否则为 0 ,即:
* `1 ^ 1` 的结果是 `0`
* `1 ^ 0` 的结果是 `1`
* `0 ^ 1` 的结果是 `1`
* `0 ^ 0` 的结果是 `0`
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
> [!NOTE]
2024-10-21 08:56:58 +00:00
>
2024-10-22 02:47:49 +00:00
> 按位异或的场景有:
2024-10-21 08:56:58 +00:00
>
2024-10-22 02:47:49 +00:00
> * ① 交换两个数值:异或操作可以在不使用临时变量的情况下交换两个变量的值。
> * ② 加密或解密:异或操作用于简单的加密和解密算法。
> * ③ 错误检测和校正异或操作可以用于奇偶校验位的计算和检测错误RAID-3 以及以上)。
> * ……
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
* 示例:`9 ^ 7 = 14`
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
![](./assets/26.svg)
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
* 示例:`-9 ^ 7 = -16`
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
![](./assets/27.svg)
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
## 6.6 按位取反
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
* 运算规则:如果二进制对应的位上是 1则结果为 0如果是 0 ,则结果为 1 。
* `~0` 的结果是 `1`
* `~1` 的结果是 `0`
2024-10-21 08:56:58 +00:00
2024-10-22 02:47:49 +00:00
* 示例:`~9 = -10`
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
![](./assets/28.svg)
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
* 示例:`~-9 = 8`
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
![](./assets/29.svg)
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
## 6.7 二进制左移
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
* 在一定范围内,数据每向左移动一位,相当于原数据 × 2。正数、负数都适用
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
* 示例:`3 << 4 = 48` 3 × 2^4
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
![](./assets/30.svg)
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
* 示例:`-3 << 4 = -48` -3 × 2 ^4
![](./assets/31.svg)
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
## 6.8 二进制右移
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
* 在一定范围内,数据每向右移动一位,相当于原数据 ÷ 2。正数、负数都适用
> [!NOTE]
2024-10-21 09:09:47 +00:00
>
2024-10-22 02:47:49 +00:00
> * ① 如果不能整除,则向下取整。
> * ② 右移运算符最好只用于无符号整数,不要用于负数。因为不同系统对于右移后如何处理负数的符号位,有不同的做法,可能会得到不一样的结果。
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
* 示例:`69 >> 4 = 4` 69 ÷ 2^4
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
![](./assets/32.svg)
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
* 示例:`-69 >> 4 = -5` -69 ÷ 2^4
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
![](./assets/33.svg)
2024-10-21 09:09:47 +00:00
2024-10-22 02:49:47 +00:00
# 第七章:三元运算符(⭐)
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
## 7.1 概述
* 语法:
2024-10-21 09:19:53 +00:00
```c
2024-10-22 02:47:49 +00:00
条件表达式 ? 表达式1 : 表达式2 ;
2024-10-21 09:19:53 +00:00
```
> [!NOTE]
>
2024-10-22 02:47:49 +00:00
> * 如果条件表达式为非 0 (真),则整个表达式的值是表达式 1 。
> * 如果条件表达式为 0 (假),则整个表达式的值是表达式 2 。
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
## 7.2 应用示例
2024-10-21 09:09:47 +00:00
* 示例:
```c
#include <stdio.h>
int main() {
2024-10-22 02:47:49 +00:00
int m = 110;
int n = 20;
int result = m > n ? m : n;
printf("result = %d\n", result); // result = 110
2024-10-21 09:09:47 +00:00
return 0;
}
```
2024-10-22 02:49:47 +00:00
# 第八章:运算符的优先级和结合性(⭐)
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
## 7.1 概述
2024-10-21 09:09:47 +00:00
2024-10-22 02:47:49 +00:00
* 在数学中,如果一个表达式是 `a + b * c` ,我们知道其运算规则就是:先算乘除再算加减。其实,在 C 语言中也是一样的先算乘法再算加减C 语言中乘除的运算符比加减的运算符的优先级要高。
2024-10-21 09:19:53 +00:00
2024-10-22 02:47:49 +00:00
## 7.2 优先级和结合性
2024-10-21 09:19:53 +00:00
2024-10-22 02:47:49 +00:00
* `优先级``结合性`的定义,如下所示:
* ① 所谓的`优先级`:就是当多个运算符出现在同一个表达式中时,先执行哪个运算符。
* ② 所谓的`结合性`:就是当多个相同优先级的运算符出现在同一个表达式中的时候,是从左到右运算,还是从右到左运算。
* `左结合性`:具有相同优先级的运算符将`从左到右`(➡️)进行计算。
* `右结合性`:具有相同优先级的运算符将`从右到左`(⬅️)进行计算。
2024-10-21 09:19:53 +00:00
2024-10-22 02:47:49 +00:00
> [!NOTE]
>
> 技巧:先看`优先级`;如果优先级相同,再看`结合性`。
* C 语言中运算符的优先级有几十个,有的运算符优先级不同,有的运算符优先级相同,如下所示:
| 优先级 | 运算符 | 名称或含义 | 结合方向 |
| ------ | -------------- | ------------------------------------------- | ------------- |
| `0` | `()` | 小括号,最高优先级 | ➡️(从左到右) |
| `1` | `++``--` | 后缀自增和自减,如:`i++``i--` 等 | ➡️(从左到右) |
| | `()` | 小括号,函数调用,如:`sum(1,2)` 等 | |
| | `[]` | 数组下标,如:`arr[0]``arr[1]` 等 | |
| | `.` | 结构体或共用体成员访问 | |
| | `->` | 结构体或共用体成员通过指针访问 | |
| `2` | `++``--` | 前缀自增和自减,如:`++i``--i` 等 | ⬅️(从右到左) |
| | `+` | 一元加运算符,表示操作数的正,如:`+2` 等 | |
| | `-` | 一元减运算符,表示操作数的负,如:`-3` 等 | |
| | `!` | 逻辑非运算符(逻辑运算符) | |
| | `~` | 按位取反运算符(位运算符) | |
| | `typename` | 强制类型转换 | |
| | `*` | 解引用运算符 | |
| | `&` | 取地址运算符 | |
| | `sizeof` | 取大小运算符 | |
| `3` | `/` | 除法运算符(算术运算符) | ➡️(从左到右) |
| | `*` | 乘法运算符(算术运算符) | |
| | `%` | 取模(取余)运算符(算术运算符) | |
| `4` | `+` | 二元加运算符(算术运算符),如:`2 + 3` 等 | ➡️(从左到右) |
| | `-` | 二元减运算符(算术运算符),如:`3 - 2` 等 | |
| `5` | `<<` | 左移位运算符(位运算符) | ➡️(从左到右) |
| | `>>` | 右移位运算符(位运算符) | |
| `6` | `>` | 大于运算符(比较运算符) | ➡️(从左到右) |
| | `>=` | 大于等于运算符(比较运算符) | |
| | `<` | 小于运算符(比较运算符) | |
| | `<=` | 小于等于运算符(比较运算符) | |
| `7` | `==` | 等于运算符(比较运算符) | ➡️(从左到右) |
| | `!=` | 不等于运算符(比较运算符) | |
| `8` | `&` | 按位与运算符(位运算符) | ➡️(从左到右) |
| `9` | `^` | 按位异或运算符(位运算符) | ➡️(从左到右) |
| `10` | `\|` | 按位或运算符(位运算符) | ➡️(从左到右) |
| `11` | `&&` | 逻辑与运算符(逻辑运算符) | ➡️(从左到右) |
| `12` | `\|\|` | 逻辑或运算符(逻辑运算符) | ➡️(从左到右) |
| `13` | `?:` | 三目(三元)运算符 | ⬅️(从右到左) |
| `14` | `=` | 简单赋值运算符(赋值运算符) | ⬅️(从右到左) |
| | `/=` | 除后赋值运算符(赋值运算符) | |
| | `*=` | 乘后赋值运算符(赋值运算符) | |
| | `%=` | 取模后赋值运算符(赋值运算符) | |
| | `+=` | 加后赋值运算符(赋值运算符) | |
| | `-=` | 减后赋值运算符(赋值运算符) | |
| | `<<=` | 左移后赋值运算符(赋值运算符) | |
| | `>>=` | 右移后赋值运算符(赋值运算符) | |
| | `&=` | 按位与后赋值运算符(赋值运算符) | |
| | `^=` | 按位异或后赋值运算符(赋值运算符) | |
| | `\|=` | 按位或后赋值运算符(赋值运算符) | |
| `15` | `,` | 逗号运算符 | ➡️(从左到右) |
> [!WARNING]
>
> * ① 不要过多的依赖运算符的优先级来控制表达式的执行顺序,这样可读性太差,尽量`使用小括号来控制`表达式的执行顺序。
> * ② 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它`分成几步`来完成。
> * ③ 运算符优先级不用刻意地去记忆,总体上:一元运算符 > 算术运算符 > 关系运算符 > 逻辑运算符 > 三元运算符 > 赋值运算符。