和数组彼此密切相关,所以,如果我们有一个二维数组
int a[3][4]={
1,2,3,4,
5,6,7,8,
9,10,11,12};
双
printf("%pn", a);
和
printf("%pn", *a);
打印相同的地址。我的理解可能是a
指向a
的基址,而*a
指向二维数组a
的第一个子数组。
那么,两者之间有什么区别呢?
我得到的可能是指向一段时间的基址 *a 指向二维数组 A 的第一个子数组。
差不多就是这样。
- 当你将指针传递给
printf
时,a
本身会衰减到指向其第一个子数组的指针(类型为int(*)[3]
(。 -
*a
指定a
的第一个子数组(类型int[3]
(,并衰减到指向该子数组的第一个元素的指针(类型int*
(。
最后,它们共享相同的值,因为数组与其第一个元素具有相同的地址,递归。
给定声明
int a[3][4];
以下情况为真:
Expression Type Decays to Value
---------- ---- --------- -----
a int [3][4] int (*)[4] Base address of array
&a int (*)[3][4] n/a Base address of array
*a int [4] int * Base address of first subarray
(equivalent to a[0])
a[i] int [4] int * Base address of i'th subarray
&a[i] int (*)[4] n/a Base address of i'th subarray
*a[i] int n/a Value of a[i][0]
a[i][j] int n/a Value of a[i][j]
&a[i][j] int * n/a Address of a[i][j]
数组第一个元素的地址与数组本身的地址相同,所以表达式a
、&a
、*a
、a[0]
、&a[0]
和&a[0][0]
都产生相同的值(数组第一个元素的地址(,但它们将具有不同的类型(int (*)[3][4]
vs。 int (*)[4]
vs. int *
(。
编辑
除非它是sizeof
或一元&
运算符的操作数,否则"T
的N元素数组"类型的表达式将被转换("衰减"(为"指向T
的指针"类型的表达式,并且表达式的值将是数组第一个元素的地址。
所以表达式*a
等价于a[0]
;两个表达式的类型都是"4-element array of int
"。由于它们不是sizeof
或一元&
运算符的操作数,因此这些表达式"衰减"为键入"指向int
的指针"。
这就是"衰减到"列显示的内容。
请参阅在线 C 2011 语言标准的第 6.3.2.1 节。
a
是一个大小为 3x4 的 2D 数组。这意味着:
-
sizeof(a) == 3*4*sizeof(int)
-
a[i]
是大小为 4 的一维数组(表示 0<=i<3( -
a[i][j]
是一个 int ( 0<=i<3 和 0<=j<4( - 当用作指针时
a
衰减到&a[0]
*a
是a[0]
:它是一个大小为 4 的一维数组。这意味着:
-
sizeof(*a) == 4*sizeof(int)
-
(*a)[i]
是一个整数 (0<=i<4( - 当用作指针时
*a
衰减到&a[0][0]
因此,a
和*a
是不同的对象,它们衰减到指向同一地址的指针,该地址也是&a
。但是a
衰减到指向int[4]
的指针,而*a
衰减到指向int
的指针(感谢undur_gongor注意到(。
指针(数组衰减到的指针(之间的区别不是地址,而是类型。
如您所见,两个指针都指向同一地址。但是a
指向子数组,而*a
指向int
s。
这会产生差异,例如在进行地址算术时。 a + 1
与*a + 1
不同。
这很简单。 *a
是一个整数数组。在您的情况下,除了数组[1,2,3,4]
之外,*a
什么都没有。这个数组的各个元素可以通过(*a)[i]
访问,其中i
是所需元素的索引。
a
是指向这个整数数组的指针。 a[0]
会给你第一个数组(它和*a
一样(,a[1]
会给你第二个数组([5,6,7,8]
(。
例如,如果你想访问第 5 个元素(即 5
(,它将a[1][0]
。