This commit is contained in:
许大仙 2024-08-26 10:53:22 +08:00
parent e9cace8803
commit 5a8618ed70
4 changed files with 123 additions and 64 deletions

View File

@ -192,17 +192,20 @@ public class Demo {
}
}
public static void main(String[] args){
int a = 10; // 用户态
int b = 20; // 用户态
int c = a + b; // 用户态
string filePath = "c:/demo.txt"; // 用户态
string txt = a + b + c; // 用户态
// 用户态
int a = 10;
int b = 20;
int c = a + b;
string filePath = "c:/demo.txt";
string txt = a + b + c;
writeFile(filePath, a); // 从用户态切换到内核态完成文件写入
// 从用户态切换到内核态完成文件写入
writeFile(filePath, a);
System.out.println(a); // 从内核态切换回用户态
System.out.println(b); // 用户态
System.out.println(c); // 用户态
// 从内核态切换回用户态
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
}
```

View File

@ -1431,25 +1431,29 @@ gcc HelloWorld.c -o HelloWorld.exe
* 预处理命令:
```shell
gcc -E 源文件.c -o 源文件.i # 通常以 .i 结尾表示这个文件是一个中间状态
# 通常以 .i 结尾表示这个文件是一个中间状态
gcc -E 源文件.c -o 源文件.i
```
* 编译(预处理和编译)命令:
```shell
gcc -S 源文件.i -o 源文件.s # 在 Linux 中,通常以 .s 结尾;在 Windows 中,通常以 .asm 结尾
# 在 Linux 中,通常以 .s 结尾;在 Windows 中,通常以 .asm 结尾
gcc -S 源文件.i -o 源文件.s
```
* 汇编(预处理、编译和汇编)命令:
```shell
gcc -c 源文件.s -o 源文件.o # 在 Linux 中,通常以 .o 结尾;在 Windows 中,通常以 .obj 结尾
# 在 Linux 中,通常以 .o 结尾;在 Windows 中,通常以 .obj 结尾
gcc -c 源文件.s -o 源文件.o
```
* 链接(预处理、编译、汇编和链接)命令:
```shell
gcc 源文件.o -o 源文件.exe # 在 Linux 中,通常以 .out 结尾;在 Windows 中,通常以 .exe 结尾
# 在 Linux 中,通常以 .out 结尾;在 Windows 中,通常以 .exe 结尾
gcc 源文件.o -o 源文件.exe
```
### 7.4.2 应用示例
@ -1716,14 +1720,15 @@ dnf -y install perf
```shell
apt -y update \
&& apt -y install linux-tools-common linux-tools-generic linux-tools-$(uname -r)
&& apt -y install linux-tools-common \
linux-tools-generic linux-tools-$(uname -r)
```
![](./assets/158.gif)
> [!NOTE]
>
> 之所以报错的原因,在于 WSL2 中的 Ubuntu 的内核是定制化的,并非 Ubuntu 的母公司 Canonical 发布的标准内核,所以需要我们手动编译安装。
> 之所以报错的原因,在于 WSL2 中的 Ubuntu 的内核是定制化的(微软自己维护的),并非 Ubuntu 的母公司 Canonical 发布的标准内核,所以需要我们手动编译安装。
* 查看内核版本:
@ -1745,11 +1750,14 @@ export KERNEL_VERSION=$(uname -r | cut -d'-' -f1)
```shell
apt -y update && \
apt -y install binutils-dev debuginfod default-jdk default-jre libaio-dev \
libbabeltrace-dev libcap-dev libdw-dev libdwarf-dev libelf-dev libiberty-dev \
liblzma-dev libnuma-dev libperl-dev libpfm4-dev libslang2-dev libssl-dev \
libtraceevent-dev libunwind-dev libzstd-dev libzstd1 python3-setuptools python3 \
python3-dev systemtap-sdt-dev zlib1g-dev bc dwarves bison flex libnewt-dev libdwarf++0 \
apt -y install binutils-dev debuginfod default-jdk \
default-jre libaio-dev libbabeltrace-dev libcap-dev \
libdw-dev libdwarf-dev libelf-dev libiberty-dev \
liblzma-dev libnuma-dev libperl-dev libpfm4-dev \
libslang2-dev libssl-dev libtraceevent-dev libunwind-dev \
libzstd-dev libzstd1 python3-setuptools python3 \
python3-dev systemtap-sdt-dev zlib1g-dev bc dwarves \
bison flex libnewt-dev libdwarf++0 \
libelf++0 libbfb0-dev python-dev-is-python3
```

View File

@ -339,7 +339,7 @@ int num = 10;
* ② 当 CPU `执行`的时候,会将变量名`替换`为具体的地址,再进行具体的操作。
> [!CAUTION]
> [!IMPORTANT]
>
> 变量名(标识符)需要符合命名规则和命名规范!!!
@ -370,9 +370,9 @@ int num = 10;
>[!NOTE]
>
>输入:从输入设备(键盘、鼠标、扫描仪)向计算机输入数据。
>* ① 输入:从输入设备(键盘、鼠标、扫描仪)向计算机输入数据。
>
>输出:从计算机向外部输出设备(显示器、打印机)输出数据。
>* ② 输出:从计算机向外部输出设备(显示器、打印机)输出数据。
![](./assets/13.png)
@ -390,9 +390,9 @@ int printf (const char *__format, ...) {
> [!NOTE]
>
> * 格式化字符串:是使用双引号括起来的字符串,里面包含了普通的字符串和格式占位符。
> * 格式占位符(格式声明符):由 `%` 和`格式字符`组成,作用是将输出的数据转换为指定的格式后输出,这里的 `%d` 表示整数。
> * 输出列表:是程序要输出的一些数据,可以是常量、变量或表达式,需要和格式占位符一一对应。
> * 格式化字符串:是使用双引号括起来的字符串,里面包含了普通的字符串和格式占位符。
> * 格式占位符(格式声明符):由 `%` 和`格式字符`组成,作用是将输出的数据转换为指定的格式后输出,这里的 `%d` 表示整数。
> * 输出列表:是程序要输出的一些数据,可以是常量、变量或表达式,需要和格式占位符一一对应。
* 在计算机中,二进制、八进制、十进制以及十六进制的英文名称和缩写,如下所示:
* 二进制binary缩写是 bin。
@ -406,7 +406,8 @@ int printf (const char *__format, ...) {
> [!IMPORTANT]
>
> 在生活中的 decimal 是小数的意思但是在计算机中decimal 的完整含义是 decimal integer ,即十进制整数。
> * ① 在生活中的 decimal 是小数的意思。
> * ② 但是在计算机中decimal 的完整含义是 decimal integer ,即十进制整数。
@ -581,7 +582,8 @@ int main() {
> [!NOTE]
>
> 在上世纪 60 - 70 年代的时候,因为国家贫穷,人民生活不富裕等原因,家长虽然会给孩子取名为:`张建国`、`李华强`等;但是,也会取小名为`二狗子`、`狗剩`等,目的是希望孩子能健康成长(养活),像 `张建国`、`李华强`、`二狗子`、`狗剩`都是名字(标识符),伴随人的一生。
> * ① 在上世纪 60 - 70 年代的时候,因为国家贫穷,人民生活不富裕等原因,家长虽然会给孩子取名为:`张建国`、`李华强`等。
> * ② 但是,也会给孩子取小名,如:`二狗子`、`狗剩`等,目的是希望孩子能健康成长(养活),像 `张建国`、`李华强`、`二狗子`、`狗剩`都是名字(标识符),伴随人的一生。
### 1.8.2 标识符的命名规范
@ -603,7 +605,8 @@ int main() {
* 示例:合法(不一定建议)的标识符
```txt
a、BOOK_sun、MAX_SIZE、Mouse、student23、Football、FOOTBALL、max、_add、num_1、sum_of_numbers
a、BOOK_sun、MAX_SIZE、Mouse、student23、
Football、FOOTBALL、max、_add、num_1、sum_of_numbers
```
@ -611,7 +614,8 @@ a、BOOK_sun、MAX_SIZE、Mouse、student23、Football、FOOTBALL、max、_add
* 示例:非法的标识符
```txt
$zj、3sum、ab#cd、23student、Foot-baii、s.com、bc、j**p、book-1、tax rate、don't
$zj、3sum、ab#cd、23student、Foot-baii、
s.com、bc、j**p、book-1、tax rate、don't
```
### 1.8.3 关键字
@ -672,8 +676,8 @@ $zj、3sum、ab#cd、23student、Foot-baii、s.com、bc、j**p、book-1、tax
>[!NOTE]
>
>* 所谓的`字面量常量`,就是可以直接使用的常量,不需要声明或定义,包括:整数常量、浮点数常量以及字符常量。
>* 所谓的`标识符常量`,就是使用标识符来作为常量名,包括: `#define` 宏定义的标识符常量、`const` 关键字修饰的标识符常量、枚举常量。
>* 所谓的`字面量常量`,就是可以直接使用的常量,不需要声明或定义,包括:整数常量、浮点数常量以及字符常量。
>* 所谓的`标识符常量`,就是使用标识符来作为常量名,包括: `#define` 宏定义的标识符常量、`const` 关键字修饰的标识符常量、枚举常量。
@ -720,7 +724,7 @@ int main() {
#define 常量名 常量值
```
> [!CAUTION]
> [!IMPORTANT]
>
> * ① 其实`宏定义`的常量的`执行时机`是在`预处理`阶段,将所有`宏常量`替换完毕,才会继续编译代码。
> * ② 不要以 `;` 结尾,如果有 `;` ,分号也会成为常量值的一部分。
@ -1159,7 +1163,8 @@ int main() {
> [!IMPORTANT]
>
> 这里讨论的适用于`有符号位`的整数int 等;而不适用于`无符号位`的整数unsinged int 等。
> * ① 这里讨论的适用于`有符号位`的整数int 等。
> * ② 这里讨论的不适用于`无符号位`的整数unsinged int 等。
![](./assets/33.svg)
@ -1167,7 +1172,8 @@ int main() {
> [!IMPORTANT]
>
> 这里讨论的适用于`有符号位`的整数int 等;而不适用于`无符号位`的整数unsinged int 等。
> * ① 这里讨论的适用于`有符号位`的整数int 等。
> * ② 这里讨论的不适用于`无符号位`的整数unsinged int 等。
![](./assets/34.svg)
@ -1191,10 +1197,8 @@ int main() {
> [!IMPORTANT]
>
> 总结:
>
> * ① 按照原码的规则,会出现 `+0``-0` 的情况,即:`0`000 0000 0000 0001+0、`1`000 0000 0000 0001-0显然不符合实际情况。
> * ② 所以,计算机底层虽然存储和计算的都是二进数,但显然不是原码。
>* ② 所以,计算机底层虽然存储和计算的都是二进数,但显然不是原码。
### 3.5.3 反码
@ -1217,10 +1221,8 @@ int main() {
> [!IMPORTANT]
>
> 总结:
>
> * ① 按照反码的规则,如果是 `+0`,对应的原码是 `0`000 0000 0000 0000那么其反码还是 `0`000 0000 0000 0000如果是 `-0`,对应的原码是 `1`000 0000 0000 0000其反码是 `1`111 1111 1111 1111显然不符合实际情况。
> * ② 所以,计算机底层虽然存储和计算的都是二进数,但显然不是反码。
>* ② 所以,计算机底层虽然存储和计算的都是二进数,但显然不是反码。
### 3.5.4 补码
@ -1254,11 +1256,9 @@ int main() {
> [!IMPORTANT]
>
> 总结:
>
> * ① 补码表示法解决了`原码`和`反码`存在的`两种`零(`+0` 和 `-0`)的问题,即:在补码表示法中,只有`一个`零,即 `0000 0000`
> * ②补码使得`加法运算`和`减法运算`可以统一处理,通过将减法运算`转换`为加法运算,可以简化硬件设计,提高了运算效率。
> * ③ 计算机底层`存储`和`计算`的都是`二进数的补码`。换言之,当`读取`整数的时候,需要采用`逆向`的转换,即:将补码转换为原码。正数的原码、反码、补码都是一样的,三码合一。负数的补码转换为原码的方法就是先减去 `1` ,得到反码,再按位取反,得到原码(符号位是不能借的)。
>* ②补码使得`加法运算`和`减法运算`可以统一处理,通过将减法运算`转换`为加法运算,可以简化硬件设计,提高了运算效率。
> * ③ 计算机底层`存储`和`计算`的都是`二进数的补码`。换言之,当`读取`整数的时候,需要采用`逆向`的转换,即:将补码转换为原码。正数的原码、反码、补码都是一样的,三码合一。负数的补码转换为原码的方法就是先减去 `1` ,得到反码,再按位取反,得到原码(符号位是不能借的)。
### 3.5.5 总结
@ -1266,7 +1266,7 @@ int main() {
* ② 正数的原码、反码和补码都是一样的,三码合一。
* ③ 负数的反码是在其原码的基础上按位取反0 变 1 1 变 0 ),符号位不变;负数的补码是其反码 + 1 。
* ④ 0 的补码是 0 。
* ⑤ 负数的补码转换为原码的方法就是先减去 `1` ,得到反码,再按位取反,得到原码。
* ⑤ 负数的补码转换为原码的方法就是先减去 `1` ,得到反码,再按位取反,得到原码(符号位是不能借位的)
## 3.6 计算机底层为什么使用补码?

View File

@ -440,9 +440,9 @@ long long num3 = 100LL; // 100LL 就是字面量
> [!NOTE]
>
> * ① 默认情况下的,整数字面量的类型是 int 类型。
> * ② 如果需要表示 long 类型的字面量,需要添加后缀 l 或 L ,建议 L。
> * ③ 如果需要表示 long long类型的字面量需要添加后缀 ll 或 LL建议 LL 。
> * ④ 如果需要表示无符号整数类型的字面量,需要添加 u 或 U建议 U 。
> * ② 如果需要表示 `long` 类型的字面量,需要添加后缀 `l``L` ,建议 `L`
> * ③ 如果需要表示 `long long` 类型的字面量,需要添加后缀 `ll``LL`,建议 `LL`
> * ④ 如果需要表示`无符号`整数类型的字面量,需要添加 `u``U`,建议 `U`
@ -608,7 +608,12 @@ int main() {
> * 如果这个数目前是`最大值`,再进行`加法`计算,数据就会超过该类型能够表示的最大值,叫做`上溢出`(如果最大值 + 1 会“绕回”到最小值)。
> * 如果这个数目前是`最小值`,再进行`减法`计算,数据就会超过该类型能够表示的最小值, 叫做`下溢出`(如果最小值 - 1 会“绕回”到最大值)。
>
> 在 C 语言中,程序产生数值溢出的时候,并不会引起错误而自动停止,是因为计算机直接按照二进制补码的运算规则进行处理;但是,这可能会导致不可预料的后果。因此,编程时要特别注意避免数值溢出,特别是在涉及大数或小数的运算时。
> [!IMPORTANT]
>
> * ① 在 C 语言中程序产生数值溢出的时候并不会引发错误而使程序自动停止是因为计算机底层直接按照二进制补码的运算规则进行处理的很多编程语言也是这样处理的Java 等)。
> * ② 但是这可能会导致不可预料的后果1996 年的亚利安5号运载火箭爆炸、2004 年的 Comair 航空公司航班停飞事故。
> * ③ 在实际开发中,编程时要特别注意,以避免数值溢出问题,特别是在涉及大数或小数的运算(特指整数)。
### 1.3.2 无符号数的取值范围
@ -749,11 +754,6 @@ $S_n = a_1 \times \frac{1 - r^n}{1 - r}$
![](./assets/9.svg)
> [!IMPORTANT]
>
> * ① 在实际开发中,选择合适的数据类型,以避免数值溢出问题!!!
> * ② 数据溢出错误会导致软件运算结果出错1996 年的亚利安5号运载火箭爆炸、2004 年的 Comair 航空公司航班停飞事故。
* 示例:无符号的上溢出和下溢出
@ -826,14 +826,25 @@ int main() {
> * ② 浮点型数据有两种表现形式:
> * 十进制数形式3.12、512.0f、0.512.512,可以省略 0
> * 科学计数法形式5.12e2e 表示基数 10、5.12E-2E 表示基数 10
> * ③ 在实际开发中,对于浮点类型,建议使用 double 类型;如果范围不够,就使用 long double 类型。
> * ③ 在实际开发中,对于浮点类型,建议使用 `double` 类型;如果范围不够,就使用 `long double` 类型。
### 1.4.2 格式占位符
* 对于 float 类型的格式占位符,是 `%f` ,默认会保留 `6` 位小数;可以指定小数位,如:`%.2f` 表示保留 `2` 位小数。
* 对于 double 类型的格式占位符,是 `%lf` ,默认会保留 `6` 位小数;可以指定小数位,如:`%.2lf` 表示保留 `2` 位小数。
* 对于 long double 类型的格式占位符,是 `%Lf` ,默认会保留 `6` 位小数;可以指定小数位,如:`%.2Lf` 表示保留 `2` 位小数。
* 如果想输出`科学计数法`形式的浮点数,则使用 `%e`
* 对于 `float` 类型的格式占位符,是 `%f` ,默认会保留 `6` 位小数,不足 `6` 位以 `0` 补充;可以指定小数位,如:`%.2f` 表示保留 `2` 位小数。
* 对于 `double` 类型的格式占位符,是 `%lf` ,默认会保留 `6` 位小数,不足 `6` 位以 `0` 补充;可以指定小数位,如:`%.2lf` 表示保留 `2` 位小数。
* 对于 `long double` 类型的格式占位符,是 `%Lf` ,默认会保留 `6` 位小数,不足 `6` 位以 `0` 补充;可以指定小数位,如:`%.2Lf` 表示保留 `2` 位小数。
> [!NOTE]
>
> * ① 如果想输出`科学计数法`形式的 `float` 类型的浮点数,则使用 `%e`
> * ② 如果想输出`科学计数法`形式的 `double` 类型的浮点数,则使用 `%le`
> * ③ 如果想输出`科学计数法`形式的 `long double` 类型的浮点数,则使用 `%Le`
> [!NOTE]
>
> * ① 浮点数还有一种更加智能的输出方式,就是使用 `%g``g` 是 `general format` 的缩写,即:通用格式),`%g` 会根据数值的大小自动判断,选择使用普通的浮点数格式(`%f`)进行输出,还是使用科学计数法(`%e`)进行输出,即:`float` 类型的两种输出形式。
> * ② 同理,`%lg` 会根据数值的大小自动判断,选择使用普通的浮点数格式(`%lf`)进行输出,还是使用科学计数法(`%le`)进行输出,即:`double` 类型的两种输出形式。
> * ③ 同理,`%Lg` 会根据数值的大小自动判断,选择使用普通的浮点数格式(`%Lf`)进行输出,还是使用科学计数法(`%Le`)进行输出,即:`long double` 类型的两种输出形式。
@ -913,8 +924,8 @@ int main() {
### 1.4.3 字面量后缀
* 浮点数字面量默认是 double 类型。
* 如果需要表示 float 类型的字面量,需要后面添加后缀 f 或 F。
* 如果需要表示 long double 类型的字面量,需要后面添加后缀 l 或 L。
* 如果需要表示 `float` 类型的字面量,需要后面添加后缀 `f``F`,建议 `F`
* 如果需要表示 `long double` 类型的字面量,需要后面添加后缀 `l``L`,建议 `L`
@ -939,7 +950,7 @@ int main() {
### 1.4.4 类型占用的内存大小(存储空间)
* 可以通过 sizeof 运算符来获取 float、double 以及 long double 类型占用的内存大小(存储空间)。
* 可以通过 `sizeof` 运算符来获取 float、double 以及 long double 类型占用的内存大小(存储空间)。
@ -980,6 +991,40 @@ int main() {
}
```
### 1.4.6 整数和浮点数的相互赋值
* 在 C 语言中,整数和浮点数是可以相互赋值的,即:
* 将一个整数赋值给小数类型,只需要在小数点后面加 0 就可以了。
* 将一个浮点数赋值给整数类型,就会将小数部分丢掉,只会取整数部分,会改变数字本身的值。
> [!WARNING]
>
> * ① 在 C 语言中浮点数赋值给整数类型会直接截断小数点后面的数编译器一般只会给出警告让我们注意一下C 语言在检查类型匹配方面不太严格,最好不要养成这样的习惯)。
> * ② 但是,在 Java 等编程语言中,这样的写法是不可以的,会在编译阶段直接报错。
* 示例:
```c
#include <stdio.h>
int main() {
// 禁用 stdout 缓冲区
setbuf(stdout, NULL);
float a = 123; // 整数赋值给浮点类型,只需要在小数点,后面加 0 即可
printf("a=%f \n", a); // a=123.000000
int b = 123.00; // 浮点赋值给整数类型,会直接截断小数点后面的数
printf("b=%d \n", b); // b=123
return 0;
}
```
## 1.5 字符类型
### 1.5.1 概述
@ -1037,7 +1082,7 @@ int main() {
### 1.5.3 类型占用的内存大小(存储空间)
* 可以通过 sizeof 运算符来获取 char 类型占用的内存大小(存储空间)。
* 可以通过 `sizeof` 运算符来获取 char 类型占用的内存大小(存储空间)。
@ -2298,3 +2343,6 @@ man ascii
- `Unicode 字符集`和对应的`UTF-8 字符编码`之间的关系,如下所示:
![](./assets/44.png)
## 3.2 小数在内存中是如何存储的?