a[6]={1,2,3,4,5,6};
内存布局
1 2 3 4 5 6
addr 2002 2006 2010 2014 2016 2020
b[2][3]={1,2,3,4,5,6};
B 的内存布局
1 2 3 4 5 6
addr 2002 2006 2010 2014 2016 2020
A 和 B 都相同
为什么a[1]
地址是2006
和b[1]
地址是2010
两者都不同。 数组是连续存储的,为什么它们不同。所以我怀疑数组中braket[][]
我们知道内存由地址而不是列和行组成的是什么。
答案在于结果的类型。几乎每当在 C 中提到数组时,它就会衰减成指向其第一个元素的指针。现在对于您的两种情况:
-
a 的类型是
int ()[6]
,在执行a[1]
隐含的指针算术之前,它会衰减成指向 intint*
的指针。表达式a[1]
正好等同于*(a + 1)
。这个指针的添加将使指针前进一int
,因为这是指针指向的。 -
b 的类型是
int ()[2][3]
它衰减为指向数组int (*)[3]
的指针。指针指向的数组的大小为三个整数。因此,*(b + 1)
将指针前进三个整数。
对于第二个数组,内存布局实际上是
+---------+---------+---------+---------+---------+---------+ |b[0][0] |b[0][1] |b[0][2] |b[1][0] |b[1][1] |b[1][2] | +---------+---------+---------+---------+---------+---------+
让我们一劳永逸地明确这一点:
首先,假设a
和b
都映射到完全相同的内存区域。也就是说,a[0]
和b[0][0]
都存储在从同一地址开始的连续内存位置。
考虑到这一点,请注意a[1]
和b[1]
不是同一个内存位置。为什么?因为a
是整数数组,而b
是整数数组数组。b
中的每个位置都是一个由 3 个整数组成的数组;a
中的每个位置都是一个整数。
因此,a[1]
与b[1]
不是相同的内存地址,因为b[1]
距离b[0][0]
3*sizeof(b[0][0])
字节,而a[1]
距离a[0]
sizeof(a[0])
字节。因此,偏移量是不同的,即使数组布局在内存中是相同的。您对a[1]
和b[1]
的混淆与索引相同但含义不同这一事实有关。
a[1]
等价于*(a+1)
,b[1]
等价于*(b+1)
。问题是,a+1
和b+1
比例 1 的数量不同(再次,分别按sizeof(a[0])
和3*sizeof(b[0][0])
)。这就是地址不同的原因。
特别是,&b[1]
与&a[3]
相同。