数组作为指针
Array as a pointer
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。这是什么。如果可能的话,请用图表解释。
欢迎来到数组指针衰减的深度。结果是:
-
x
的类型是3D阵列int ()[2][2][2]
。 -
如果你取它的地址,没有什么特别的事情发生,你会得到一个指向该数组的指针,即
&x
的类型是int (*)[2][2][2]
。 -
然而,在大多数其他上下文中,数组不是直接使用的,它们首先衰减为指向其第一个元素的指针。因此,在表达式
*x
中,x
首先衰减为类型为int (*)[2][2]
的指针(3D阵列的第一个元素是2D阵列)。然后该指针被解引用以产生2D阵列CCD_ 8。 -
由于3D阵列的第一个切片是首先存储的,因此其地址与3D阵列的地址相同。即CCD_ 9和CCD_。
-
当您第二次取消引用
&**x
时,也会发生同样的情况,CCD_11会为您提供3D阵列中第一行的地址(其类型为int (*)[2]
)。 -
同样,第三次取消引用时也会发生同样的情况,
&***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
(尽管它可能会显示类似的结果,此时您需要开始了解指针是关于什么的)。
- 指向指向字符数组的指针数组的指针
- 通过指向指针数组的指针访问子类的属性
- C++,指针数组,指向双链表中的条目
- 在C++中,如何初始化指向wchar_t*的指针数组(生成wchar_t**)
- C++从函数指针数组调用函数
- 关于指向指针数组的指针
- 将返回值存储在函数指针数组的指针中是如何工作的?
- 将链表转换为指针数组时出错
- C++ 对象指针数组的复制构造函数
- C++ - 循环访问指针数组会导致错误
- 删除指针数组 (C++) 中的元素
- 如何循环访问 cpp 中的函数返回的字符指针数组
- 将函数指针数组中的函数指针作为模板参数传递
- Google Or-Tools Glop:如何创建指向 const 对象的指针数组?
- 具有推导参数的模板函数指针数组变量
- 如何模板化堆栈分配的多态指针数组到接口,包括派生类型的相应点?
- C++指针数组到字符数组中的特定位置
- 如何在C++中复制指针数组的数据
- 初始化类中的指针数组,并在另一个类中检索它
- 尽管直接设置了指针数组,但仍为空