C++中的多维数组和指针

3

假设我在C++中声明和初始化了以下多维数组:

unsigned a[3][4] = {
    {12, 6, 3, 2},
    {9, 13, 7, 0},
    {7, 4, 8, 5}
};

然后我执行这段代码:

cout << a << endl; // output: 0x7fff5afc5bc0
cout << a + 1 << endl; // output: 0x7fff5f0afbd0
cout << *a << endl; // output: 0x7fff5afc5bc0
cout << *a + 1 << endl; // output: 0x7fff5f0afbc4

我不太理解在这里发生了什么。

  1. a 是第一个元素的地址,对吧?在单维数组中,*a 应该是第一个元素的值,但是它的值与 a 相同?!在这个情况下,*a 到底是什么意思?

  2. 为什么 a + 1*a + 1 不同?


4
很多这样的帖子都在 Stack Overflow 上,可以搜索一下。 - P0W
尝试对 *(*a + 1)**(a+1) 进行解引用,你就会看到它们各自指向的位置。 - vsoftco
请记住,二维数组的第一个元素是一个一维数组。 - M.M
2个回答

3
你应该尝试查找一些关于指针、数组和数组指针衰减的好文档。在你的情况下,unsigned a[3][4] 是一个类型为 unsigned [3][4] 的二维数组。每当你将其称为 a 时,它会衰减为指向 unsigned[4] 的指针,因此 a 的衰减类型是 unsigned (*)[4]。因此,对其进行解引用会给你一个数组,所以 *a 就是数组 [12, 6, 3, 2](严格来说,它是指向数组第一个元素的指针)。
现在,a+1 的意思是“将指向 unsigned[4] 的指针增加 1”,在你的例子中,它在内存中“跳过”了 4 个 unsigneds,所以现在 a+1 指向你的示例中索引为 1 的“行”。对其进行解引用 *(a+1) 得到的是数组本身([9,13,7,0])(即其第一个元素的指针),再次解引用会得到第一个元素,即 **(a+1) 等于 9
另一方面,*a+1 首先对 a 进行解引用,因此你得到第一行,即 [12,6,3,2](再次强调,严格来说是该行的第一个元素的指针)。然后你将其增加了一个,所以最终它指向了元素 6。再次解引用,*(*a+1) 就得到了 6
定义等价于 a 可能会有所帮助。
typedef unsigned T[4]; // or (C++11) using T = unsigned[4];
T a[3]; // Now it's a bit more clear how dereferencing works

2

二维数组是由数组组成的数组。 你可以将 a 视为

a = { a[0], a[1], a[2]} 

并且 a[0]a[1]a[2] 分别代表

a[0] = { a[0][0], a[0][1], a[0][2], a[0][3]};
a[1] = { a[1][0], a[1][1], a[1][2], a[1][3]};
a[1] = { a[2][0], a[2][1], a[2][2], a[2][3]};

分析您的第一个问题

a 是第一个元素的地址,对吗?

是的,a 是第一个元素的地址,而 a 的第一个元素是 a[0],它是 a[0][0] 的第一个元素的地址。

*a 应该是第一个元素的值,但为什么它和 a 相同呢?

是的,*a 应该是指向 a[0] 的第一个元素的值。我们可以看到,a[0]a[0][0] 的地址,因此 a 也是一样的。因此,*aa 具有相同的值,即 a[0][0] 的地址。

在这个上下文中,*a 的意思是什么?

之前已经回答过了,*a 是第一个数组的第一个元素 a[0][0] 的地址,*(a+1) 是第二个数组的第一个元素 a[1][0] 的地址。

分析您的第二个问题

为什么 a + 1 不同于 *a + 1

此时,您可能可以自己回答这个问题。

aa[0] 的地址,那么
a+1a[1] 的地址,它保存了 a[1][0] 的地址。您可以通过打印值来验证。

cout<<**(a+1)<<endl; // 9

另一种方式是*a表示a[0]的值,即a[0][0]的地址。 因此,*a+1表示a[0][1]的地址。您可以打印该值:

cout<<*(*a+1)<<endl; // 6

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接