为什么在 C/C++ 中的多维数组中 a[0] 与 a 相同?

Why in multi-dimentional array in C/C++ a[0] is same as a?

本文关键字:相同 数组 C++ 为什么      更新时间:2023-10-16

我有以下程序

#include<stdio.h>
int main() {
int a[3][3]={{1,2,3},
{4,5,6},
{7,8,9}};
printf("%pn",a);
printf("%pn",a[0]);
printf("%pn",*(a+0));
}

它给了我以下输出:

6356716
6356716
6356716

我期望,给定一个基址,例如6356716,那么*(6356716+0)将产生该位置内的值(即1(。

因此,如果数组名称等效于指向其第一个值的指针,如上面的表达式所示,打印"a"应将指针打印到其第一个值,即 a[0](它本身在位置 6356716 处衰减到其第一个元素(。在这种情况下,为什么取消引用在这里不起作用,*(a+0)计算结果为*(6356716+0)

a是一个由 3 个数组组成的数组,每个数组的数组为 3 个int。当在表达式中用作sizeof、一元&_Alignof的操作数时,它会自动转换为指向其第一个参数的指针,这是一个 3int的数组。如果正确打印此指针,它将显示该数组的地址 3int

a[0]a中的第一个元素,所以它是一个3int的数组。在表达式中使用时,除上述相同例外情况外,它会自动转换为指向其第一个元素的指针,即int。如果正确打印此指针,它将显示该int的地址。

由于数组只是连续存储的对象序列,因此数组从其第一个元素的同一位置开始。因此,打印的结果aa[0]显示相同的地址。

*(a+0)a[0]相同,因此打印它的结果相同。

不应使用%u打印地址。打印带有%u的指针具有未定义的行为。在某些情况下,它可能在您的实现中似乎有效,但在其他情况下会中断。要打印地址,请使用%p,并将指针转换为void *const void *

printf("%pn", (const void *) a);
printf("%pn", (const void *) a[0]);
printf("%pn", (const void *) *(a+0));

首先你需要了解的是,一个二维数组被当作一个数组的数组,二维数组的所有元素都存储在连续的内存位置,现在第二个要了解的是数组名称实际上给出了其中第一个元素的地址。所以你的第一个printf语句实际上printf("%un",a);给你a[0]的地址,因为a[0]是这个2D数组中的第一个元素。现在你的第二个printf语句printf("%un",a[0]);给你a[0][0]的地址,因为a[0]实际上是2D数组中第一个数组的名称。现在你的最后一个printf语句printf("%un",*(a+0));实际上是编译器内部处理数组的方式,它与第二个完全相同。从解释中可以清楚地看出,这三个语句指的是同一个地址,但这并不意味着它们是同一回事,与上面解释的第二个和第三个语句相比,第一个语句的含义不同。虽然这三个语句给你的地址是1,这是2D数组的第一个元素。

printf("%un", a);
printf("%un", a[0]);

a衰减到指向a第一个元素的指针,a[0]衰减到指向a[0]的第一个元素的指针。等效地,您可以使用:

printf("%un", &a[0]);
printf("%un", &a[0][0]);

从对象类型的角度来看,&a&a[]&a[0][0]是完全不同的指针类型。但是,如果您查看 2D 数组的内存布局,您会发现,从纯数字的角度来看&a==&a[]==&a[0][0].

此外,"%u"不是打印指针的正确格式。您应该使用"%p".

printf("%pn", a);
printf("%pn", a[0]);