我读了一些课堂讲稿,为了让指针引用二维数组,必须给它第一个元素的地址。

int a[10][10];
int *p = &a[0][0];

我从来没有试过这样做,所以我很好奇为什么不足以将数组本身分配给指针,就像我们在1D情况下所做的那样。
int a[10][10];
int *p = a;

无论如何,数组都被保存在一个不间断的“行”内存中,2D数组只有不同的类型,但结构与1D数组相同。
通过这样做
int *p = &a[0][0];

我看不出我们怎么给指针更多的信息
int *p = a;

或者所有数组,不管它们的维数是多少,都有相同的类型,唯一的区别是多维数组在第一个元素之前存储额外的维数,我们需要跳过那些记住数组维数的内存空间?

最佳答案

首先,一些背景:
除非它是sizeof或一元&运算符的操作数,或是用于在声明中初始化另一个数组的字符串文字,否则“N-element array ofT”类型的表达式将转换为“pointer toT”类型的表达式(“decay”,表达式的值将是数组第一个元素的地址。
给出了声明

int a[10][10];

表达式具有“10个元素数组的10个元素数组的a”类型。除非此表达式是int或一元sizeof运算符的操作数,否则它将转换为“指向&的10元素数组的指针”或int类型的表达式。
鉴于上述声明,以下所有内容均属实:
    Expression    Type                Decays to
    ----------    ----                ---------
             a    int [10][10]        int (*)[10]
            &a    int (*)[10][10]
            *a    int [10]            int *
          a[i]    int [10]            int *
         &a[i]    int (*)[10]
         *a[i]    int
       a[i][j]    int
      &a[i][j]    int *

也,
    sizeof a        == sizeof (int) * 10 * 10
    sizeof &a       == sizeof (int (*)[10][10])
    sizeof *a       == sizeof (int) * 10
    sizeof a[i]     == sizeof (int) * 10
    sizeof &a[i]    == sizeof (int (*)[10] )
    sizeof *a[i]    == sizeif (int)
    sizeof a[i][j]  == sizeof (int)
    sizeof &a[i][j] == sizeof (int *)

请注意,不同的指针类型int (*)[10]int (*)[10][10]int (*)[10]不必具有相同的大小或具有相同的表示形式,尽管在我熟悉的平台上是这样。
数组的第一个元素的地址与数组本身的地址相同;因此,所有int *a&aa[0]&a[0]&a[0][0]都将产生相同的值,但类型不同(如上表所示)。
因此,假设我们添加以下声明:
int           *p0 = &a[0][0]; // equivalent to int       *p0 = a[0];
int     (*p1)[10] = &a[0];    // equivalent to int (*p1)[10] = a;
int (*p2)[10][10] = &a;

所有的p0p1p2最初都有相同的值,即a中第一个元素的地址;但是,由于指针类型不同,涉及指针运算的结果操作也不同。表达式p0 + 1将产生下一个int对象(&a[0][1])的地址。表达式p1 + 1将产生int&a[1][0])的下一个10元素数组的地址。最后,表达式p2 + 1将生成int的下一个10元素数组的地址(实际上,&a[11][0])。
注意p1p2的类型;两者都不是简单的int *,因为用于初始化它们的表达式不是那种类型(请参阅第一个表)。
注意模式;对于数组类型,表达式越简单,对应的类型就越复杂。表达式a不是指单个int对象;它是指一个10x10个int对象数组,因此当它出现在表达式中时,它被视为指向整数数组的指针,而不是指向单个整数的指针。

10-04 22:01
查看更多