C语言中数组地址赋值给int指针的疑问及输出差异解析
问题解答
先纠正一个关键误解
数组名i不是指针,只是在大多数表达式场景中(比如赋值给指针变量、作为函数参数)会被隐式转换为指向数组首元素的指针(int*类型)。但数组本身是一块连续的内存区域,和指针是完全不同的实体。
关于&i的类型
&i的类型是int(*)[3],也就是指向包含3个int元素的数组的指针,而不是你以为的指向指针的指针(int**)。这是因为i代表整个数组,取它的地址自然得到指向整个数组的指针。
为什么int* p = &i;能编译(带警告)
C语言允许不同类型的指针之间进行隐式转换(尽管这属于不安全操作,所以编译器会发出警告)。从数值上看,&i(整个数组的起始地址)和&i[0](首元素的地址)是完全相同的,所以赋值后p的地址值和数组首元素地址一致,但p的类型是int*,和&i的int(*)[3]类型不匹配。
为什么*p输出1,*(&i)输出首元素地址
*p:p是int*类型,解引用操作*p会读取p指向地址处的一个int大小的数据。因为p的地址和i[0]的地址相同,所以读取到的就是数组首元素的值1。*(&i):&i是int(*)[3]类型,解引用*(&i)得到的是整个数组i(类型为int[3])。而在printf的参数中,数组名又会被隐式转换为指向首元素的指针(int*类型)。你用%d来打印指针值,实际上是把指针的地址数值以十进制形式输出,所以看起来是首元素的地址(正确的做法应该用%p格式符打印指针)。
内容的提问来源于stack exchange,提问作者Giao Le Xuan
相关产品推荐
相关产品推荐

