关于C语言中指向10元素数组的指针(int (*p)[10])的疑问
数组指针的解引用逻辑解析
先把你的代码整理如下:
int main() { int a = 10; int *pa = &a; printf("Value of pa : %p\n", pa); // 0x7fffd215b5b8 printf("Value of *pa : %d\n", *pa); // 10 int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int (*parr)[10] = &arr; printf("Address of arr : %p\n", &arr); // 0x7fffd215b5d0 printf("Address of parr : %p\n", &parr); // 0x7fffd215b5c0 printf("Value of parr : %p\n", parr); // 0x7fffd215b5d0 printf("Value of *parr : %p\n", (*parr)); // 0x7fffd215b5d0 <---WHY? printf("Value of first element : %d\n", **parr); //1 // 使用指针parr打印数组元素 for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) printf("%d\t", *((*parr)+i)); // 1 2 3 ... 数组中存储的值 return 0; }
问题1:为什么*parr输出数组基地址而非第一个元素值1?
- 首先明确
parr的类型:int (*parr)[10]是指向包含10个int元素的数组的指针,它存储的是整个数组arr的地址(注意:&arr和arr数值上相等,但类型完全不同——arr是数组类型,会隐式转成int*;&arr是数组指针类型int(*)[10])。 - 对
parr解引用(*parr)得到的是整个数组arr本身。而在C语言中,数组名在绝大多数表达式场景下会自动转换成指向数组第一个元素的指针(仅当数组名作为sizeof、&、_Alignof的操作数时例外)。所以*parr在这里被隐式转换为int*类型,指向数组第一个元素的地址,用%p打印自然输出数组的基地址。 - 如果要得到第一个元素的值,需要对
*parr再解引用一次(**parr),或者写成(*parr)[0],这时候才是访问数组的第一个元素。
问题2:为什么需要两次解引用才能获取数组元素,且parr并非双指针?
- 两次解引用的逻辑:
- 第一次解引用
*parr:将指向整个数组的指针转换为数组本身,再隐式转为指向数组首元素的int*指针; - 第二次解引用
**parr:对这个首元素指针解引用,最终拿到数组第一个元素的数值。
- 第一次解引用
parr不是双指针的原因:双指针是int**,本质是指向指针的指针,存储的是一个int*类型变量的地址;而int (*parr)[10]是指向数组的指针,存储的是整个数组的地址,两者类型完全不同。可以通过步长验证:parr+1会跳过整个数组的大小(比如10个int共40字节),而int**类型的指针p+1只会跳过一个指针的大小(比如8字节)。
补充:关于数组指针的元素访问
你代码里的*((*parr)+i)其实等价于(*parr)[i]或者arr[i],都是访问数组第i个元素的写法。因为*parr是指向首元素的int*指针,(*parr)+i就是指向第i个元素的地址,解引用后就得到对应的值。
内容的提问来源于stack exchange,提问作者Bittu970
相关产品推荐
相关产品推荐

