From 313cf9febad83e305ebd0c97e70857509e267573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E5=A4=A7=E4=BB=99?= <1900919313@qq.com> Date: Mon, 26 Aug 2024 11:17:32 +0800 Subject: [PATCH] c --- docs/notes/01_c-basic/03_xdx/index.md | 34 +++++++++++++++++---------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/docs/notes/01_c-basic/03_xdx/index.md b/docs/notes/01_c-basic/03_xdx/index.md index f4f547a..2092adb 100644 --- a/docs/notes/01_c-basic/03_xdx/index.md +++ b/docs/notes/01_c-basic/03_xdx/index.md @@ -597,11 +597,11 @@ int main() { ### 1.3.1 概述 -* 在生活中,如果一个容器的容量是固定的,我们不停的向其中注入水,那么当容器中充满水之后,继续注入,就会溢出,如下所示: +* 在生活中,如果一个容器的容量是固定的,我们不停的向其中注入水,那么当容器中充满水之后,再继续注入,水就会从杯子中溢出来,如下所示: ![](./assets/3.jpg) -* 在程序中也是一样的,各种整数类型在内存中占用的存储单元是不同的,如:short 在内存中占用 2 个字节的存储单元,int 在内存中占用 4 个字节的存储单元。这也就意味着,各种整数类型只能存储有限的数值,当数值过大或多小的时候,超出的部分就会被直接截掉,那么数值就不能正确的存储,我们就将这种现象就称为`溢出`(overflow)。 +* 在程序中也是一样的,各种整数类型在内存中占用的存储单元是不同的,如:short 在内存中占用 2 个字节的存储单元,int 在内存中占用 4 个字节的存储单元。这也就意味着,各种整数类型只能存储有限的数值,当数值过大或多小的时候,超出的部分就会被直接截掉,那么数值就不能被正确的存储,我们就将这种现象就称为`溢出`(overflow)。 > [!NOTE] > @@ -611,8 +611,8 @@ int main() { > [!IMPORTANT] > -> * ① 在 C 语言中,程序产生数值溢出的时候,并不会引发错误而使程序自动停止,是因为计算机底层直接按照二进制补码的运算规则进行处理的(很多编程语言也是这样处理的,如:Java 等)。 -> * ② 但是,这可能会导致不可预料的后果,如:1996 年的亚利安5号运载火箭爆炸、2004 年的 Comair 航空公司航班停飞事故。 +> * ① 在 C 语言中,程序产生数值溢出的时候,并不会引发错误而使程序自动停止,这是因为计算机底层是采用二进制补码的运算规则进行处理的(很多编程语言也是这样处理的,如:Java 等)。 +> * ② 但是,这可能会导致不可预料的后果,如:1996 年的亚利安 5 号运载火箭爆炸、2004 年的 Comair 航空公司航班停飞事故。 > * ③ 在实际开发中,编程时要特别注意,以避免数值溢出问题,特别是在涉及大数或小数的运算(特指整数)。 ### 1.3.2 无符号数的取值范围 @@ -1349,7 +1349,8 @@ int main() { #include /** - * 不同的整数类型混合运算时,宽度较小的类型会提升为宽度较大的类型,比如 short 转为 int ,int 转为 long 等。 + * 不同的整数类型混合运算时,宽度较小的类型会提升为宽度较大的类型。 + * 比如 short 转为 int ,int 转为 long 等。 */ int main() { @@ -1357,7 +1358,8 @@ int main() { int i = 20; - // s1 是 short 类型,i 是 int 类型,当 s1 和 i 运算的时候,会自动转为 int 类型后,然后再计算。 + // s1 是 short 类型,i 是 int 类型。 + // 当 s1 和 i 运算的时候,会自动转为 int 类型后,然后再计算。 int result = s1 + i; printf("result = %d \n", result); @@ -1379,7 +1381,8 @@ int main() { int n2 = -100; unsigned int n3 = 20; - // n2 是有符号,n3 是无符号,当 n2 和 n3 运算的时候,会自动转为无符号类型后,然后再计算。 + // n2 是有符号,n3 是无符号。 + // 当 n2 和 n3 运算的时候,会自动转为无符号类型后,然后再计算。 int result = n2 + n3; printf("result = %d \n", result); @@ -1396,14 +1399,16 @@ int main() { #include /** -* 不同的浮点数类型混合运算时,宽度较小的类型转为宽度较大的类型,比如 float 转为 double ,double 转为 long double 。 +* 不同的浮点数类型混合运算时,宽度较小的类型转为宽度较大的类型。 +* 比如 float 转为 double ,double 转为 long double 。 */ int main() { float f1 = 1.25f; double d2 = 4.58667435; - // f1 是 float 类型,d2 是 double 类型,当 f1 和 d2 运算的时候,会自动转为 double 类型后,然后再计算。 + // f1 是 float 类型,d2 是 double 类型。 + // 当 f1 和 d2 运算的时候,会自动转为 double 类型后,然后再计算。 double result = f1 + d2; printf("result = %.8lf \n", result); @@ -1427,7 +1432,8 @@ int main() { int n4 = 10; double d3 = 1.67; - // n4 是 int 类型,d3 是 double 类型,当 n4 和 d3 运算的时候,会自动转为 double 类型后,然后再计算。 + // n4 是 int 类型,d3 是 double 类型。 + // 当 n4 和 d3 运算的时候,会自动转为 double 类型后,然后再计算。 double result = n4 + d3; printf("%.2lf", result); @@ -1470,7 +1476,7 @@ int main() { } ``` -### 1.6.3 强制类型转换 +### 1.7.3 强制类型转换 * 隐式类型转换中的宽类型赋值给窄类型,编译器是会产生警告的,提示程序存在潜在的隐患,如果非常明确地希望转换数据类型,就需要用到强制(或显式)类型转换。 * 语法: @@ -1479,7 +1485,7 @@ int main() { 数据类型 变量名 = (类型名)变量、常量或表达式; ``` -> [!CAUTION] +> [!WARNING] > > 强制类型转换可能会导致精度损失!!! @@ -1513,7 +1519,9 @@ int main(){ > [!NOTE] > -> 这些存储单元中,存储的都是 0 和 1 这样的数据,因为计算机只能识别二进制数。 +> * ① 操作系统其实并不会直接操作实际的内存,而是会通过内存管理单元(MMU)来操作内存,并通过虚拟地址映射(Virtual Address Mapping)将程序使用的虚拟地址转换为物理地址。虚拟地址映射可以实现内存保护、内存共享和虚拟内存等功能,使得程序能够使用比实际物理内存更大的内存空间,同时确保程序间不会相互干扰。 +> * ② 为了方便初学者学习,后文一律会描述 CPU 直接操作内存(这种说法不严谨,但足够简单和方便理解)。 +> * ③ 这些存储单元中,存储的都是 0 和 1 这样的数据,因为计算机只能识别二进制数。 ![](./assets/17.svg)