假设我有一个数组 int a[] = {2, 3, 4};
为什么指向第一个元素 &a[0]
的指针可以指向数组元素或一般的值,而指针 &a 不能?
cout << (&a[0])[1]; // 3
cout << (&a)[0]; // some weird adress (presumably of the array itself
cout << (&a)[1];
// a higher adress probably the adress after the end of the array so &a + 0xC (length of array) + 0x1
指针本身 (&a)、类型(带有 int (*)...的东西)是否像某种数组?
答案 0 :(得分:3)
数组和指针是 C++ 中的两种不同类型,它们之间有足够的相似性,如果不能正确理解它们,就会造成混淆。指针是初学者最难掌握的概念之一,这一事实也无济于事。
所以我认为需要快速速成课程。
int a[3] = {2, 3, 4};
这将创建一个名为 a
的数组,其中包含 3 个元素。
数组定义了数组下标操作符:
a[i]
计算数组的第 i
个元素。
int val = 24;
int* p = &val;
p
是指向对象 val
的地址的指针。
指针定义了间接(解引用)运算符:
*p
计算 p
指向的对象的值。
指针给你一个对象在内存中的地址。它可以是上面示例中的“独立对象”,也可以是作为数组一部分的对象。指针类型和指针值都无法告诉您它是哪一种。只是程序员。这就是为什么
指针还定义了数组下标运算符:
p[i]
计算 i
指向的对象“右侧”的第 p
个元素。这假定 p
的对象指针是数组的一部分(除了在 p[0]
中它不需要是数组的一部分)。
请注意,p[0]
等价于(完全相同)*p
。
在大多数情况下,数组名称会衰减为指向数组中第一个元素的指针。这就是为什么许多初学者认为数组和指针是一回事的原因。事实上他们不是。它们是不同的类型。
回到你的例子。
<块引用>为什么指向第一个元素 &a[0]
的指针可以指向数组元素或一般的值,
现在我希望你能看到,如果 p
指向数组 arr
的第一个元素,那么 p[i]
等价于 arr[i]
。由于 &a[0]
是指向数组第一个元素的指针,因此 (&a[0])[i]
等价于 a[i]
。
...但是指针 &a
不能?
正如我上面所说,数组不是指针。
因此,指向数组的指针与指向数组第一个元素的指针不同。获取数组的地址是数组名称不会衰减到指向其第一个元素的指针的少数实例之一。
所以 &a
是指向数组的指针,不是指向数组第一个元素的指针。数组和数组的第一个元素都从相同的地址开始,因此两者的值(&a
和 &a[0]
)是相同的,但它们的类型不同,这在您应用对它们取消引用或数组下标运算符:
表达 | 表达式类型 | 解引用/数组下标 表达式 |
解引用/数组下标 类型 |
---|---|---|---|
a |
int[3] |
*a / a[i] |
int |
&a |
int (*) [3] (指向数组的指针) |
*&a / &a[i] |
int[3] |
&a[0] |
int * |
*&a[0] / (&a[0])[i] |
int |
答案 1 :(得分:1)
&a
是指向数组的指针。当你间接通过那个指针时,你会得到指向的数组。
&a[0]
是 - 就像你说的 - 一个指向数组元素的指针。当您通过该指针间接访问时,您将获得指向的元素。