二维数组名称第一个元素

时间:2017-09-05 04:30:08

标签: c arrays multidimensional-array

每天一小时的C编程有这样的引用:

  

与一维数组一样,多维数组的名称是指向第一个数组元素的指针。

#include <stdio.h>

int m[2][4];

int main() {
    printf("%p\n", m);        // 1
    printf("%p\n", &(m[0]));  // 2
    printf("%p\n", m[0]);     // 3
    printf("%p\n", &m[0][0]); // 4
}

这会为所有语句打印相同的值。根据引用,1 == 2和3 == 4是有意义的。但我不明白2 == 3.如何m[0]的地址与m[0]相同?

3 个答案:

答案 0 :(得分:4)

当分配二维(或任何维度)数组时,它只占用其元素的内存(内存未分配给数组名称或任何其他数组元素,如{{1}在你的情况下,m[0]和const指针一样。)

因为没有任何物理内存分配给那些(实际上甚至不需要),所以在尝试打印时会得到相同的地址。在你的情况下, 因为它是一个二维数组,因为m[1]指向m,而m[0]又指向m[0][0],所有这些的提取地址将提供相同的值(同样适用于m[1]m[1][0])。

**为了更好地理解,请看这个(如果你打印它们会是这样的)

      _____         _____         _____
     |0x100|  -->  |0x100|  -->  |value|
0x100|_____|  0x100|_____|  0x100|_____|
       m            m[0]         m[0][0]

* value是m [0] [0]

的值

下面,   mm[0]就像指针一样,但没有物理实现(不占用内存),编译器处理如何处理它们。

*虽然我已向0x1000x100显示m包含m[0],但0x100实际上包含m[0][0]的数据/值,但是如果你做任何编译器处理它们的操作。

**正因为如此,int *p = malloc(n * sizeof(int))这是可能的,因为p现在占用了指向数组起始地址的内存。如果您将p视为int const *p,则可以将其视为没有动态分配的普通数组。

答案 1 :(得分:3)

数组包含数据,它不包含任何其他内容。这个数据有一个地址,从它开始 - 这是第一个元素的地址。

&#34;多维数组的名称是指向第一个数组元素的指针&#34;是过度简化而不是真的正确。数组不是指针,指针不是数组。

但是,只要在表达式中使用,数组的名称(任何维度)都会生成一个指向数组第一个元素的临时指针。这通常被称为&#34;数组衰减成指针&#34;。

现在,这些行之间唯一不同的是指针的类型:

  1. 类型int[2][4]的数组衰减为指向第一个元素的指针。 2D数组中的第一个元素是int [4]类型的一维数组。指向此类数组的指针是数组指针int (*)[4]

  2. &m[0]给出第一个元素的地址,即第一个1D数组的地址。所以这完全相当于1)。

  3. m[0]给出了第一个元素,仍然是一维数组。哪个衰变成指向其第一个元素的指针。 int [4]的第一个元素是int,因此我们得到一个指向int*的指针。

  4. &m[0][0]给出指向第一个数组的第一个元素int*的指针。相当于3)。

  5. 所有这些指针类型都具有相同的地址,因为2D数组从与第一个项目1D数组相同的地址开始。而这又从与第一个项目相同的地址开始,即第一个整数。

    各种不同的指针类型只是高级语言语法。这些类型不会持续存在于机器代码中,其中一切都只是原始地址。

答案 2 :(得分:0)

第一维将存储子阵列(行)的地址。

E.g。您有m[2][4],因此m[0]评估包含从m[0][0]m[0][3]的元素的第一行的地址,m[1]评估第二行的地址包含来自{的元素{1}}至m[1][0]

如果您尝试打印m[1][3]m[0],您会看到地址差异是m[1]字节之间行的总大小。