C语言中指向数组的指针输出异常的原因探究
问题分析:数组指针的寻址与运算符优先级问题
先看你给出的代码:
#include<stdio.h> int main() { int (*p)[3]; int a[3]={10,11,12}; p=&a; printf("%d\n", *p[0]); printf("%d\n", *p[1]); printf("%d\n", *p[2]); return 0; }
你发现第一个printf输出10符合预期,但后面两个输出不对,核心原因是运算符优先级和数组指针的寻址逻辑没弄明白,咱们一步步拆解:
1. 先搞懂p的类型
int (*p)[3]; 定义的是一个指向包含3个int元素的数组的指针,不是普通的int指针。也就是说,p的“步长”是一个int[3]数组的大小(通常是12字节,假设int占4字节),每次p+1都会跳过一整个3元素int数组的空间。
当你执行p=&a;时,p指向了数组a的起始地址(因为&a的类型就是int(*)[3],和p的类型完全匹配),这一步是没问题的。
2. 关键:*p[0]和*p[1]的运算逻辑
C语言里,[]运算符的优先级比*高,所以表达式会先执行[]运算:
- 对于
*p[0]:先算p[0],等价于*(p + 0),也就是p指向的那个数组(也就是a),然后*p[0]就等价于*a,也就是数组a的第一个元素a[0],所以输出10,符合预期。 - 对于
*p[1]:先算p[1],等价于*(p + 1)。因为p是指向int[3]的指针,p+1会跳过整个3元素int数组,指向a数组后面的未知内存区域。*p[1]就是取这个未知区域的第一个int值,自然不是a[1]的11了。同理*p[2]是跳过两个3元素数组的位置,取更后面的随机值。
3. 怎么修正才能输出预期的11和12?
如果要访问数组a的第2、3个元素,需要先把p解引用得到数组a(或者说数组的首地址),再用[]访问元素,也就是用(*p)[1]和(*p)[2]:
(*p)[1]:先执行*p得到数组a(等价于a),然后(*p)[1]就是a[1],输出11。(*p)[2]同理,对应a[2],输出12。
修正后的代码如下:
#include<stdio.h> int main() { int (*p)[3]; int a[3]={10,11,12}; p=&a; printf("%d\n", *p[0]); // 等价于(*p)[0],输出10 printf("%d\n", (*p)[1]); // 正确输出11 printf("%d\n", (*p)[2]); // 正确输出12 return 0; }
内容的提问来源于stack exchange,提问作者Kawsar Ahmed
相关产品推荐
相关产品推荐

