int main()
{
int x[2][2][2]={1,2,3,4,5,6,7,8};
printf("%d%d%d%d",&x,&*x,&**x,&***x);
}
显示的输出是-28 -28 -28 -28。 有人可以请求expalin这个scenerio.address是-28。它指向-28。如果可能的话,请用图解释。
答案 0 :(得分:1)
欢迎使用数组指针衰减的深度。会发生什么:
x
的类型是3D数组,int ()[2][2][2]
。
如果你拿它的地址,没有什么特别的事情,你得到一个指向那个数组的指针,i。即&x
的类型为int (*)[2][2][2]
。
但是,在大多数其他上下文中,数组不是直接使用的,它们首先衰减成指向其第一个元素的指针。因此,在表达式*x
中,x
首先衰减为类型int (*)[2][2]
的指针(3D数组的第一个元素是2D数组)。然后取消引用此指针以生成2D数组int ()[2][2]
。
由于首先存储3D阵列的第一个切片,因此其地址与3D阵列的地址相同。 I. e。 &x
和&*x
会产生相同的地址。
第二次取消引用时会发生同样的事情&**x
会为您提供3D数组中第一行的地址(其类型为int (*)[2]
)。
同样,当您第三次取消引用时会发生同样的事情,&***x
是数组中第一个元素的地址(其类型为int*
)。
数组指针衰减的机制允许C严格按照指针算法定义数组下标运算符。关键是,所涉及的三种数组类型中的每一种都具有不同的大小,这允许编译器推导出正确的偏移量。 I. e。 sizeof(*x)
为4*sizeof(int)
(请记住*x
的类型为int ()[2][2]
),sizeof(**x)
为2*sizeof(int)
。因此,x[1][0]
和x[0][1]
会解析为3D数组中的两个不同的线阵列。
答案 1 :(得分:0)
格式说明符%d
用于类型int
。你给它一些其他类型,因此,程序的行为是未定义的。您可能想尝试%p
(虽然它可能会显示类似的结果,此时您需要开始了解指针的内容)。
答案 2 :(得分:0)
结果相同,但它们的类型与下面所示的不同。 首先必须要知道“类型为T的n个元素数组”类型的表达式已经衰减 到“类型为T的指针”,但当array是&,sizeof运算符或字符串文字的操作数时有例外。
表达
&a // type is int(*)[2][2][2]
&*a // type is int(*)[2][2]
&**a // type is int(*)[2]
&***a // type is int *
在上述情况下,您总是使用&
运算符,这意味着表达式不会衰减为“T型指针”,如前所述。
请注意,all的输出将相同,但它们的类型不同,输出将是数组的基址。如果你写
int (*p)[2][2][2] = &a; // note types are same as shown above
//print p here
现在,如果你这样做
p++;
printf("%p",p);
注意p
的两个值之间的差异。然后你必须注意到p
跳过整个数组,即所有8个元素。
如果你这样做
int (*q)[2][2] = &*a; // note types are same
与
相同int(*q)[2][2] = &a[0];
之后你做
q++;
然后打印q
并注意原始q
和更新q
的值之间的差异。您会发现它现在指向内存中的下一个位置。
所以差异就在于此。
同时在您的问题中将%d
更改为%p
。