这两种声明之间的区别 int *p = arr;int (*r)[3] = arr; 第二个声明中使用了错误的初始值设定项。用作初始值设定项的数组arr被隐式转换为指向其类型int *的第一个元素的指针。因此,在第二个声明中,初始化对象和初始值设定项具有不同的指针类型,并且类型之间没有隐式转换。 要使第二个声明正确,你需要写 int (*r)[3] = &arr; 现在,指针p和r存储相同的值:数组占用的内存范围的地址,但类型不同。 例如,如果你要写 printf( "sizeof( *p ) = %zu\n", sizeof( *p ) );printf( "sizeof( *r ) = %zu\n", sizeof( *r ) ); 然后,第一个调用将输出int类型的对象的大小,该对象等于4,而第二个调用将输出int[3]类型的整个数组的大小,该数组等于12。 这是你对printf的呼唤 printf("%u %u", p, r); 指针使用了不正确的转换说明符。相反,你必须写作 printf("%p %p", ( void * )p, ( void * )r); 表达式r[0]、r[1]、r[2]的类型为int[3]。在这次通话中使用 printf("\n%d %d %d", r[0], r[1], r[2]); 如前所述,它们被隐式转换为指向第一个元素的指针。但是,