数组在内存中的图解

博客主要针对对数组在内存相关知识茫然的读者,涉及数组在内存中的情况,重点提及堆内存和栈内存,帮助读者探究其中奥秘。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于在这块知识有点茫然的读者,可以查看揣摩其中的奥秘

### 三、指针数组数组指针的区别 指针数组数组指针是C语言中两个容易混淆的概念,它们的核心区别在于 **数据类型和内存布局**。以下从定义、访问方式、典型应用场景等方面进行详细说明,并结合图解帮助理解。 #### 3.1 指针数组(Pointer Array) 指针数组是一个数组,其每个元素都是指针。它常用于存储多个指向不同数据块的地址,适用于字符串数组、命令行参数处理、动态二维数组等场景。 ```c char *names[] = {"Alice", "Bob", "Charlie"}; // 指针数组 ``` 内存布局如下: ``` ptr_arr: [0x1000] [0x1004] [0x1008] ← 数组本身的地址 ↓ ↓ ↓ &"Alice" &"Bob" &"Charlie" ← 每个元素是一个指针 ↓ ↓ ↓ "Alice" "Bob" "Charlie" ← 实际字符串内容 ``` 指针数组在访问时,通过数组下标访问指针,再通过指针访问实际数据。这种结构比固定大小的二维数组更灵活,每个字符串长度可以不同,节省内存空间[^4]。 #### 3.2 数组指针(Array Pointer) 数组指针是一个指针,它指向一个完整的数组。与普通指针不同,数组指针在进行指针算术时,移动的步长是整个数组的大小,而不是单个元素的大小。 ```c int arr[5] = {10, 20, 30, 40, 50}; int (*p_array)[5] = &arr; // 指向整个数组的指针 ``` 指针 `p_array` 指向的是整个 `arr` 数组,而不是其某个元素。当执行 `p_array + 1` 时,地址会增加 `5 * sizeof(int)` 字节,而不是 `sizeof(int)` 字节。这在访问二维数组时非常有用。 例如: ```c int arr[4][4] = { /* 初始化二维数组 */ }; int (*p)[4] = arr; // p 是指向长度为4的整型数组的指针 ``` 通过 `p[i][j]` 可以访问二维数组的每个元素,且访问效率更高[^3]。 #### 3.3 图解对比 | 指针数组(Pointer Array) | 数组指针(Array Pointer) | |---------------------------|-----------------------------| | 存储多个指针 | 指向一个完整的数组 | | 典型形式:`char *names[]` | 典型形式:`int (*p)[5]` | | 每个元素是一个地址 | 整个指针指向一个数组 | | 适合字符串数组、动态分配 | 适合访问二维数组 | 图示如下: ``` 指针数组: +-------+-------+-------+ | ptr1 | ptr2 | ptr3 | ← 数组元素是地址 +-------+-------+-------+ ↓ ↓ ↓ "data1" "data2" "data3" ← 实际数据 数组指针: +-------------------+ | 指向整个数组 | ← 一个指针指向数组整体 +-------------------+ ↓ +----+----+----+----+ | a0 | a1 | a2 | a3 | ← 数组内容 +----+----+----+----+ ``` #### 3.4 示例代码对比 以下代码演示了普通指针与数组指针在指针算术中的行为差异: ```c #include <stdio.h> int main() { int arr[5] = {10, 20, 30, 40, 50}; int *p_normal = arr; // 普通指针 int (*p_array)[5] = &arr; // 数组指针 printf("=== 普通指针 (int *) ===\n"); for (int i = 0; i < 5; i++) { printf("p_normal + %d: %p 值: %d\n", i, (void *)(p_normal + i), *(p_normal + i)); } printf("\n=== 数组指针 (int (*)[5]) ===\n"); for (int i = 0; i < 2; i++) { printf("p_array + %d: %p\n", i, (void *)(p_array + i)); } printf("\n指针步长对比:\n"); printf("普通指针 p_normal + 1 地址差:%ld 字节\n", (char *)(p_normal + 1) - (char *)p_normal); printf("数组指针 p_array + 1 地址差:%ld 字节\n", (char *)(p_array + 1) - (char *)p_array); return 0; } ``` 输出结果表明: - 普通指针每次移动 `sizeof(int)`(通常是4字节)。 - 数组指针每次移动 `5 * sizeof(int)`(即20字节)[^2]。 #### 3.5 总结 - **指针数组**:是一个数组,元素为指针,适合存储多个地址,如字符串数组。 - **数组指针**:是一个指针,指向一个数组,适合访问二维数组或进行数组整体操作。 - 二者在语法、访问方式、内存布局和指针算术上存在显著差异。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值