C语言中sizeof测试数组指针大小问题

本文深入探讨了数组指针的概念及其与数组名的关系,解释了如何通过数组指针访问数组元素,并对typedef的正确使用进行了说明,强调了其不能与赋值操作同时使用的特点。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
	int arr[5] = {1, 2, 3, 4, 5};
	int(*p)[5] = &arr;
	//typedef与赋值操作不能同时使用。
	typedef int(*P)[5];
	//p指向的是整个数组的地址
	//printf("%d\n", (*p)[1]);
	P arr_p;
	//数组指针所代表的是数组的首地址,及整个数组的地址。
	//所以在测试(*p)的字节大小时,与数组名相同。
	printf("%d\n", sizeof(arr));//20
	printf("%d\n", sizeof(*p));//20
	printf("%d\n", sizeof(*arr_p));//20

	system("pause");
	return 0;
}

一.数组名与数组指针变量的关系

arr的内容是首元素的地址,&arr的内容是这个数组的地址。

数组指针的本质就是指针,这个指针指向数组的首地址,即这个数组的地址。

对数组数组指针进行间接寻(*)址操作得到的就是数组的首元素地址。所以,再对*p进行间接寻址或下标访问时,就可以得到之后的数组中的元素了。

二.typedef的一些问题

此外,在使用typedef对变量起别名的同时,不能够对变量进行赋值操作。

typedef一般对构建好的类型起别名(在此案例中,需要先定义数组指针,再使用typedef)。

<think> 我们正在讨论C语言中的指针数组数组指针的区别、用法和示例。根据提供的引用材料,我们可以总结如下: 1. **定义区别**: - **指针数组**:首先是一个数组数组中的每个元素都是指针。例如:`int *p[10];` 表示一个包含10个元素的数组,每个元素都是指向整型的指针。 - **数组指针**:首先是一个指针,它指向一个数组。例如:`int (*p)[10];` 表示一个指针,指向一个包含10个整数的数组。 2. **内存布局**: - 指针数组:在内存中,指针数组是一个连续的块,每个元素是一个指针(通常占用4或8字节,取决于系统)。这些指针可以指向内存中不同位置的数据。 - 数组指针:它本身是一个指针,存储的是一个数组的首地址。当对该指针进行加减运算时,它以整个数组为单位进行偏移。 3. **用法示例**: - 指针数组常用于存储多个字符串(字符串数组)或动态创建的多级数据结构(如动态数组数组)。 - 数组指针常用于处理二维数组,特别是当需要传递二维数组给函数时。 4. **代码示例**: - 引用[3]中提供了使用数组指针指针数组访问二维数组的示例代码。 5. **常见错误**: - 混淆声明:如将`int *p[10]`(指针数组)和`int (*p)[10]`(数组指针)混淆。 - 内存管理:指针数组中的每个指针可能指向动态分配的内存,需要逐个释放。 6. **应用场景**: - 指针数组:适合管理长度不一的字符串数组或动态分配的行长度不等的二维数组。 - 数组指针:适合处理固定行宽的二维数组,特别是作为函数参数传递。 下面我将按照用户要求组织回答,包括区别、用法和示例,并生成相关问题。 </think> ### C语言指针数组数组指针详解 #### 1. **核心定义与语法区别** | **特性** | **指针数组** | **数组指针** | |----------------|---------------------------------------------|---------------------------------------------| | **本质** | 元素为指针数组 | 指向整个数组指针 | | **声明语法** | `int *arr[5];` <br>(* 靠近变量名) | `int (*ptr)[5];` <br>(* 被括号包裹) | | **优先级** | `[]` 优先级高于 `*` | `()` 强制 `*` 优先结合 | | **内存布局** | ![指针数组内存图](https://via.placeholder.com/150x60?text=指针数组内存) <br>连续存储指针 | ![数组指针内存图](https://via.placeholder.com/150x60?text=数组指针内存) <br>单个指针指向数组首地址 | #### 2. **访问方式对比** ```c // 指针数组示例 char *names[3] = {"Alice", "Bob", "Charlie"}; printf("%c", *(names[0] + 1)); // 输出 'l'(访问第一个字符串的第二个字符) // 数组指针示例 int matrix[3][4] = {0}; int (*p)[4] = matrix; // 指向含4个元素的数组 printf("%d", (*p)[2]); // 输出 matrix[0][2] ``` #### 3. **典型应用场景** **指针数组优势场景**: - 管理不等长字符串集合 ```c char *langs[] = {"Python", "C", "JavaScript"}; ``` - 动态创建交错数组(Jagged Array) ```c int *rows[3]; for(int i=0; i<3; i++) rows[i] = malloc((i+1)*sizeof(int)); // 每行长度不同 ``` **数组指针优势场景**: - 传递二维数组到函数 ```c void printMatrix(int (*mat)[4], int rows) { for(int i=0; i<rows; i++) { for(int j=0; j<4; j++) printf("%d ", mat[i][j]); // 直接下标访问 } } ``` - 处理固定维度的多维数组 ```c int arr[3][4]; int (*p)[4] = arr; // 正确匹配第二维度 ``` #### 4. **内存模型深度解析** **指针数组内存布局**: ``` names[0] → "Alice\0" names[1] → "Bob\0" names[2] → "Charlie\0" ``` - `names` 占连续 $3 \times \text{sizeof}(char*)$ 字节 - 各字符串独立存储在内存任意位置[^4] **数组指针内存布局**: ``` ptr → [0][1][2][3] // 完整数组块 ``` - 指针运算以整个数组为单位:`ptr+1` 前进 $4 \times \text{sizeof}(int)$ 字节 - 等价关系:`(*ptr)[i] ≡ ptr[0][i]` #### 5. **常见错误与规避** ```c // 错误1:混淆声明 int *p[5]; // 指针数组 int (*q)[5]; // 数组指针 // 错误2:维度不匹配 int arr[3][5]; int (*p)[4] = arr; // 编译警告!第二维度不匹配 // 正确用法:动态分配 int (**ptrArr) = malloc(3*sizeof(int*)); // 指针数组 int (*arrPtr)[5] = malloc(3*sizeof(int[5])); // 数组指针 ``` #### 6. **性能与适用性分析** | **指标** | 指针数组 | 数组指针 | |---------------|----------------------------|----------------------------| | 内存局部性 | ❌ 数据分散存储 | ✅ 连续内存访问 | | 灵活性 | ✅ 支持不等长结构 | ❌ 固定维度 | | 访问效率 | ⚠️ 需两次解引用 | ✅ 直接偏移计算 | | 函数参数传递 | ️ 需传递长度参数 | ✅ 自动携带维度信息[^3] | > 关键建议:处理矩形数据(如图像)优先用数组指针;处理不规则数据(如字符串集合)用指针数组[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值