我原以为第一个 printf() 语句会出现垃圾值,但我得到了地址。为什么?
#include<stdio.h>
int main()
{
int (*p)[10];
int a[10]={1,2,3,4,5,6,7,8,9,0};
p=a+10;
printf("%d\n",*(p));
printf("%u",(p));
}
最佳答案
首先,此声明
p=a+10;
无效。
赋值左侧的类型为 int( * )[10]
而赋值右侧的类型为 int *
并且没有隐式从一种类型到另一种类型的转换。
你必须写
p = ( int( * )[10] )( a + 10 );
其次是printf
的这些调用
printf("%d\n",*(p));
printf("%u",(p));
具有未定义的行为,因为使用了无效的转换说明符 d
和 u
以及指针类型的参数,因为 *p
和 p
都是指针。
因此,一个有效的程序可以如下所示
#include <stdio.h>
int main(void)
{
int (*p)[10];
int a[10]={1,2,3,4,5,6,7,8,9,0};
p = ( int( * )[10] )( a + 10 );
printf("%p\n",( void * )*p );
printf("%p\n", (void *)p );
return 0;
}
指针可以指向对象(或数组)最后一个元素后面的内存。
所以在这句话之后
p = ( int( * )[10] )( a+10 );
指针p
指向一个想象的二维数组的第一个元素,其中的元素又是int[10]
类型的一维数组,并且想象的二维数组的第一个元素对应于数组a
。
表达式*p
也是一个指针。它的类型是 int *
因为表达式 *p 给出了 int[10]
类型的左值,并且在表达式中这个左值被隐式转换为指向其第一个元素的指针(在本例中的类型为 int
)。
因此表达式 p
和 *p
都指向相同的内存并具有相同的值。
程序输出证明了这一点
0x7ffcfd46ea48
0x7ffcfd46ea48
这两个指针 p
和 *p
之间的区别在于它们可能指向的对象的类型。
考虑以下演示程序
#include <stdio.h>
int main(void)
{
int (*p)[10];
int a[10]={1,2,3,4,5,6,7,8,9,0};
p = ( int( * )[10] )( a+10 );
printf("%zu\n",sizeof( *p ) );
printf("%zu\n",sizeof( **p ) );
return 0;
}
它的输出是
40
4
如果你这样写,你可能会得到未定义的行为
printf( "%d\n", **p );
在本例中,表达式 **p
的类型为 int
,并且可以访问数组 a
之外的内存。
关于c - C 中的垃圾值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57495601/