我读了一些课堂讲稿,为了让指针引用二维数组,必须给它第一个元素的地址。
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
、&a
、a[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;
所有的
p0
、p1
和p2
最初都有相同的值,即a
中第一个元素的地址;但是,由于指针类型不同,涉及指针运算的结果操作也不同。表达式p0 + 1
将产生下一个int
对象(&a[0][1]
)的地址。表达式p1 + 1
将产生int
(&a[1][0]
)的下一个10元素数组的地址。最后,表达式p2 + 1
将生成int
的下一个10元素数组的地址(实际上,&a[11][0]
)。注意
p1
和p2
的类型;两者都不是简单的int *
,因为用于初始化它们的表达式不是那种类型(请参阅第一个表)。注意模式;对于数组类型,表达式越简单,对应的类型就越复杂。表达式
a
不是指单个int
对象;它是指一个10x10个int
对象数组,因此当它出现在表达式中时,它被视为指向整数数组的指针,而不是指向单个整数的指针。