C语言中指向数组首元素的指针与指向数组的指针有什么区别
C语言两类指针的差异解答
你对两个指针的判断完全正确,二者本质是不同类型的指针,虽然指向的内存地址数值可能相同,但编译器对二者的处理逻辑完全不同,使用时的差异也非常明显。
首先先修正示例代码的一处常见写法问题:
int arr[5] = {1,2,3,4,5}; int *pointer = arr; // 原代码直接赋值arr会触发类型不匹配警告,正确写法需要取整个数组的地址 int (*pointer2)[5] = &arr;
1. 类型本质区别
pointer是 指向int类型的指针,存储的是数组首元素arr[0]的地址,对应你说的「指向数组首元素的指针」。pointer2是 指向包含5个int元素的数组的指针(数组指针),存储的是整个数组arr的起始地址,就是你说的「指向包含5个int元素的数组的指针」。
注:数组的起始地址和数组首元素的起始地址在内存上是同一个位置,所以直接打印两个指针的数值会完全一致,二者的差异只存在于编译期的类型处理逻辑。
2. 实际使用中的核心差异
2.1 指针运算步长不同
指针加减的步长由其指向的类型大小决定:
pointer + 1的步长是sizeof(int),32位int环境下偏移4字节,指向arr[1]的地址。pointer2 + 1的步长是sizeof(int[5]),32位int环境下偏移20字节,直接跳过整个5元素数组,指向arr结束后的下一块内存地址。
示例输出:
// 假设arr的起始地址为0x7ffdabcdef10 printf("%p\n", pointer); // 输出0x7ffdabcdef10 printf("%p\n", pointer + 1); // 输出0x7ffdabcdef14 printf("%p\n", pointer2); // 输出0x7ffdabcdef10 printf("%p\n", pointer2 + 1); // 输出0x7ffdabcdef24(10的16进制+20=24)
2.2 解引用结果不同
- 对
pointer解引用*pointer得到的是int类型的数值,等于arr[0]的值1,可以直接参与数值运算。 - 对
pointer2解引用*pointer2得到的是int[5]数组类型,等价于数组名arr,必须再取下标才能得到单个元素的值:(*pointer2)[0]才等于arr[0]的值1。
2.3 赋值的类型约束不同
int*类型的指针可以直接接收退化为指针的数组名arr,不会有编译警告。- 数组指针
int (*)[5]只能接收&arr这种取整个数组地址的右值,直接赋值arr会触发编译器的类型不匹配警告。
3. 常见使用场景
int*是操作数组的最常用指针类型,一般用来遍历数组元素、读写单个元素值。- 数组指针
int (*)[N]一般用于操作二维数组、或者作为函数参数传递固定长度的数组,可以在编译期做长度校验,避免数组越界。
内容的提问来源于stack exchange,提问作者user737163
相关产品推荐
相关产品推荐

