问题描述
#include<stdio.h>
int main()
{
int arr[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
printf("%u,%u\n",arr,&arr+1);
return 0;
}
在打印语句中:(假设整数大小为4个字节)
令arr的内存位置为1000
arr+1--给出1016(即下一行内存)
1000 1004 1008 1012 1016
1 2 3 4 5
&arr+1 给出 1048
我理解逻辑,但我无法理解编译器如何识别
arr 作为“指向 4 个整数数组的指针” 和
&arr 作为“指向 4 个整数的 3 个数组的数组的指针”
即使两者在递增前都指向同一个地址(1000)
解决方法
arr
是 int
的 4 元素数组的 3 元素数组。
表达式中的数组会自动转换为指向数组第一个元素的指针(存在一些例外)。因此 arr
被转换为指向其第一个元素的指针。第一个元素的类型是“int
的四元素数组,所以arr
被转换为“一个指向int
的四元素数组的指针”({{1} }).
一元int(*)[4]
(地址)运算符的操作数是例外之一。 &
是 arr
的 4 元素数组的 3 元素数组,所以 int
是“指向 &arr
的 4 元素数组的 3 元素数组的指针”。
注意行
int
通过将类型错误的数据传递给 printf("%u,%u\n",arr,&arr+1);
来调用 未定义的行为。 printf()
期望 %u
。您应该将指针转换为 unsigned int
并使用 void*
打印如下指针:
%p
或者,您可以将指针转换为整数(以实现定义的方式)并打印它们。
printf("%p,%p\n",(void*)arr,(void*)(&arr+1));
,
在表达式中使用的数组指示符在极少数例外情况下被转换为指向它们的第一个元素的指针。
所以数组 arr
声明为
int arr[3][4] = { /*...*/ };
当 用作 printf 调用的参数时,它被转换为指向其第一个元素的指针。数组元素的类型是int[4]
。因此,指向此类型对象的指针的类型为 int ( * )[4]
。
另一方面,表达式 &arr
的类型为 int ( * )[3][4]
。像 &arr + 1
这样递增指针会产生比表达式 &arr
的值大 sizeof( int[3][4] )
(等于 12 * sizeof( int )
)的值。
注意必须使用转换说明符%p
来输出指针的值。
printf("%p,(void * )arr,( void * )( &arr+1 ) );