【问题标题】:Why in multi-dimentional array in C/C++ a[0] is same as a?为什么在 C/C+ 中的多维数组中 a[0] 与 a 相同?
【发布时间】:2019-01-24 18:40:39
【问题描述】:

我有以下程序

#include<stdio.h>

int main() {
    int a[3][3]={{1,2,3},
                {4,5,6},
                {7,8,9}};

    printf("%p\n",a);
    printf("%p\n",a[0]);
    printf("%p\n",*(a+0));
}

它给了我以下输出:

6356716
6356716
6356716

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

所以,如果一个数组名等价于一个指向它的第一个值的指针,就像上面的表达式,打印'a'应该打印指向它的第一个值的指针,即a[0](它本身衰减到它在位置的第一个元素6356716)。在那种情况下,为什么取消引用在这里不起作用,*(a+0) 评估为 *(6356716+0)?

【问题讨论】:

  • C/C++ == UB 请选择一种语言
  • 此代码中的任何内容实际上都没有引用 (即 1)。第二次和第三次打印是等效的。
  • What is array decaying?的可能重复
  • 不一样所以你的问题没有意义。
  • @pmg 很好的类比。只是*(a+0)a[0]一模一样。

标签: c++ c pointers multidimensional-array


【解决方案1】:

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

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

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

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

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

printf("%p\n", (const void *) a);
printf("%p\n", (const void *) a[0]);
printf("%p\n", (const void *) *(a+0));

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      当用于

      printf("%u\n", a);
      printf("%u\n", a[0]);
      

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

      printf("%u\n", &a[0]);
      printf("%u\n", &a[0][0]);
      

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

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

      printf("%p\n", a);
      printf("%p\n", a[0]);
      

      【讨论】:

      • UB:printf 指针格式错误。发送地址是一样的,但是引用的对象不一样(有不同的类型)。
      • @P__J__,你是对的。我只是在解决核心问题,但我已经稍微更新了答案。
      猜你喜欢
      • 1970-01-01
      • 2021-04-25
      • 1970-01-01
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      • 2015-09-14
      • 2013-08-24
      • 2019-02-20
      相关资源
      最近更新 更多