diff --git a/docs/notes/01_c-basic/05_xdx/assets/37.svg b/docs/notes/01_c-basic/05_xdx/assets/37.svg new file mode 100644 index 0000000..602ad9d --- /dev/null +++ b/docs/notes/01_c-basic/05_xdx/assets/37.svg @@ -0,0 +1,4 @@ + + + +
00000000
00000000
00000000
00001010
内存条
地址:0x0100
地址:0x0101
地址:0x0102
地址:0x0103

                                                              

① 在内存中开辟 4 个连续的空间,去存储 10 的二进制(补码)。

② 将开辟的内存空间的首地址赋值给变量 a 。                               

③ 根据变量 a 中保存的首地址 + 数据类型占用的内存空间,就可以很方便的存取数据了。
a
int 
= 10 ;
\ No newline at end of file diff --git a/docs/notes/01_c-basic/05_xdx/assets/38.svg b/docs/notes/01_c-basic/05_xdx/assets/38.svg new file mode 100644 index 0000000..b75e1a0 --- /dev/null +++ b/docs/notes/01_c-basic/05_xdx/assets/38.svg @@ -0,0 +1,4 @@ + + + +
00000000
00000000
00000000
00000001
内存条
地址:0x0100

                                                              

① 在内存中开辟 12 个连续的空间,去存储 1,2,3 的二进制(补码)。

② 将开辟的内存空间的首地址赋值给数组变量 a 。                               

③ 根据数组变量 a 中保存的首地址 + 数据类型占用的内存空间,就可以很方便的存取数据了。(数组名[索引] 是一种简化写法)
arr
int 
[]  = { 1 , 2, 3 };
00000000
00000000
00000000
00000010
00000000
00000000
00000000
00000011

索引 0

索引 1

索引 2
地址:0x0104
地址:0x0108
索引 0、1、2 其实是偏移量,arr[0] 就是偏移 0 的单位(int),arr[1] 就是偏移 1 个单位(int),... 依次类推
\ No newline at end of file diff --git a/docs/notes/01_c-basic/05_xdx/index.md b/docs/notes/01_c-basic/05_xdx/index.md index 1d9c591..5360b26 100644 --- a/docs/notes/01_c-basic/05_xdx/index.md +++ b/docs/notes/01_c-basic/05_xdx/index.md @@ -1386,13 +1386,13 @@ int main() { -# 第六章:内存中的变量和数组(⭐) +# 第五章:内存中的变量和数组(⭐) -## 6.1 内存和内存地址 +## 5.1 内存和内存地址 -### 6.1.1 内存 +### 5.1.1 内存 -* `内存`是一种`计算机硬件`,就是`软件`在`运行过程`中,用来`临时存储数据`的。在生活中,最为常见的`内存`就是`随机存取存储器(RAM,内存条`),其特点如下所示: +* `内存`是一种`计算机硬件`,是`软件`在`运行过程`中,用来`临时存储数据`的。在生活中,最为常见的`内存`就是`随机存取存储器(RAM,内存条`),其特点如下所示: * ① 生活中最常见的内存类型,用于存储当前运行的程序和数据。 * ② 内存是易失性存储器,这意味着断电后数据会丢失。 * ③ 它具有高速读写特性,适用于需要快速访问的操作。 @@ -1428,7 +1428,7 @@ int main() { > * ① 将数据`保存`到内存中。 > * ② 从内存中的`对应位置`将数据`取出来`。 -### 6.1.2 内存地址 +### 5.1.2 内存地址 * 在这个计算机的内存条,动不动就 32GB、64GB 、128GB 或更高的年代,如下所示: @@ -1467,11 +1467,11 @@ int main() { * 之所以,加了内存地址,就能加快数据的存取速度,可以类比生活中的`字典`: - * 如果没有使用`拼音查找法`或`部首查找法`,我们需要一页一页,一行一行的在整个字典中去搜索我们想要了解的汉字。 + * 如果没有使用`拼音查找法`或`部首查找法`,我们需要一页一页,一行一行的,在整个字典中去搜索我们想要了解的汉字。 ![](./assets/32.gif) - * 如果使用`拼音查找法`或`部首查找法`,我们可以很快的定位到所要了解汉字的所在的页数,加快了搜索的效率。 + * 如果使用`拼音查找法`或`部首查找法`,我们可以很快的定位到所要了解汉字所在的页数,加快了搜索的效率。 ![](./assets/33.jpg) @@ -1523,5 +1523,88 @@ int main() { > * ③ 在 32 位操作系统上,内存地址以 32 位的二进制数字表示,最大支持的的内存是 4 GB,所以 32 位操作系统已经被淘汰。 > * ④ 在 64 位操作系统上,内存地址以 64 位的二进制数字表示,由于表示形式太长,我们通常会转为十六进制,以方便阅读。 -## 6.2 内存中的变量 +## 5.2 内存中的变量 + +* 在 C 语言中,数据类型的种类很多,如:short、int、long、float、double、char 等。以 int 类型为例,在 32 位或 64 位操作系统中的,int 类型的变量都是占 4 个字节,当我们在代码中这么定义变量,如: + +```c +#include + +int main(){ + + // 定义一个变量并初始化 + int a = 10; + + return 0; +} +``` + +* 那么,编译器就会这么处理,如下所示: + +![](./assets/37.svg) + +* 在代码中,我们可以使用 `&变量名` 来获取一个变量的内存首地址,如下所示: + +```c +#include + +int main() { + + // 定义一个变量并初始化 + int a = 10; + + printf("变量 a 的首地址是: %p\n", &a); // 变量 a 的首地址是: 0000002bf1dffd0c + printf("变量 a 的中保存的值是: %d\n", a); // 变量 a 的中保存的值是: 10 + + return 0; +} +``` + +## 5.3 内存中的数组 + +* 如果我们在代码中这么定义数组,如下所示: + +```c +#include + +int main(){ + + // 定义一个数组并初始化 + int arr[] = {1,2,3}; + + return 0; +} +``` + +* 那么,编译器就会这么处理,如下所示: + +![](./assets/38.svg) + +* 在代码中,我们可以直接打印数组名的内存地址,如下所示: + +```c +#include + +int main() { + + int arr[] = {1, 2, 3}; + + printf("arr 的首地址是: %p \n", arr); // arr 的首地址是: 0000003a6f7ffcd4 + printf("arr 的首地址是: %p \n", &arr); // &arr 的地址是: 0000003a6f7ffcd4 + printf("arr[0] 的地址是: %p \n", &arr[0]); // arr[0] 的地址是: 0000003a6f7ffcd4 + printf("arr[1] 的地址是: %p \n", &arr[1]); // arr[1] 的地址是: 0000003a6f7ffcd8 + printf("arr[2] 的地址是: %p \n", &arr[2]); // arr[2] 的地址是: 0000003a6f7ffcdc + + return 0; +} +``` + +> [!WARNING] +> +> 在上述示例中,`arr` 和 `&arr` 的值是一样的,但是对应的含义是不同的。 +> +> * ① `arr` 是数组名,在大多数情况下会转换为数组第一个元素的地址,即:`arr` 等价于 `&arr[0]`,其数据类型是 `int *`。 +> * ② `&arr`是数组名的地址,即整个数组的地址,它指向数组本身,并不是数组第一个元素的地址,`&arr` 的数据类型是 `int(*)[3]`。 + +