数组作为指针

Array as a pointer

本文关键字:指针 数组      更新时间:2023-10-16
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。有人能解释一下这个场景吗?a的地址是28。它指向28。这是什么。如果可能的话,请用图表解释。

欢迎来到数组指针衰减的深度。结果是:

  1. x的类型是3D阵列int ()[2][2][2]

  2. 如果你取它的地址,没有什么特别的事情发生,你会得到一个指向该数组的指针,即&x的类型是int (*)[2][2][2]

  3. 然而,在大多数其他上下文中,数组不是直接使用的,它们首先衰减为指向其第一个元素的指针。因此,在表达式*x中,x首先衰减为类型为int (*)[2][2]的指针(3D阵列的第一个元素是2D阵列)。然后该指针被解引用以产生2D阵列CCD_ 8。

  4. 由于3D阵列的第一个切片是首先存储的,因此其地址与3D阵列的地址相同。即CCD_ 9和CCD_。

  5. 当您第二次取消引用&**x时,也会发生同样的情况,CCD_11会为您提供3D阵列中第一行的地址(其类型为int (*)[2])。

  6. 同样,第三次取消引用时也会发生同样的情况,&***x是数组中第一个元素的地址(其类型为int*)。

数组指针衰减的机制允许C严格根据指针算术来定义数组下标运算符。关键是,所涉及的三种数组类型中的每一种都有不同的大小,这允许编译器推断出正确的偏移量。即sizeof(*x)4*sizeof(int)(记住*x的类型是int ()[2][2]),sizeof(**x)2*sizeof(int)。因此,x[1][0]x[0][1]解析为3D阵列中的两个不同的线阵列。

结果是相同的,但它们的类型不同,如下所示。您首先必须意识到,类型为"T类型的n元素数组"的表达式已衰减转换为"T类型的指针",但数组是&的操作数时除外;,sizeof运算符或字符串文字。

表达式

&a  // type is  int(*)[2][2][2]
&*a // type is int(*)[2][2]
&**a // type is int(*)[2]
&***a // type is int  *

在上述情况下,您总是使用&运算符,这意味着表达式不会像前面解释的那样衰减为"T类型的指针"。请注意,所有的输出都是相同的,但它们的类型不同,并且输出将是数组的基地址。以下是区别,如果你写

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++;

然后打印CCD_ 26,并注意原始CCD_。您会发现它现在指向内存中下一个位置的4。所以这里的区别就来了。还要将问题中的%d更改为%p

格式说明符%d用于类型int。您给它一些其他类型,因此,程序的行为是未定义的。您可能想要尝试%p(尽管它可能会显示类似的结果,此时您需要开始了解指针是关于什么的)。