如果 arr[3] 是一个数组而 ptr 是一个指针,那么为什么 arr 和 &arr 给出相同的结果而 ptr 和 &ptr 不

If arr[3] is an array and ptr is a pointer, then why do arr and &arr give same result but ptr and &ptr don't

我是数据结构和算法的初学者,现在开始研究指针,在问这里的问题之前我读了 this recommended post 但我不明白所以我在这里问问题。

朋友告诉我数组名是指向数组第一个值的指针,如arr returns arr[0], arr+1 returns arr[1] 的地址,所以当我写这个

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int i = 10;
    int arr[3] = {1, 2, 3};
    int *ptr = &i;
    cout << arr << "   " << &arr << endl;
    cout << ptr << "   " << &ptr;
    return 0;
}

arr&arr都给同样的结果

0x61ff00 0x61ff00

ptr&ptr 给出不同的结果

0x61ff0c 0x61fefc

谁能告诉我为什么会这样?

数组不是指针!

数组在各种情况下都会衰减到指向其第一个元素的指针。例如 std::cout << arr; 实际上打印了数组第一个元素的内存地址。 std::cout << &arr; 打印数组的内存地址。由于第一个元素的地址与数组的地址相同,因此您会看到相同的值。

但是,仅仅因为它们具有相同的值,并不意味着它们是相同的。 arr 可以衰减为 int*,而 &arr 是指向数组的指针,int(*)[3].

我希望以下内容能帮助大家理清头绪:

#include <iostream>
#include <type_traits>


void make_it_decay(int x[]) {
    std::cout << std::is_same_v< decltype(x), int*> << "\n";
}

int main() {
    int arr[3] = {1,2,3};

    //std::cout << (arr == &arr) << "\n";  // does not compile !
    std::cout << (arr == &(arr[0])) << "\n";

    std::cout << std::is_same_v< decltype(arr), int[3]> << "\n";
    std::cout << std::is_same_v< decltype(&arr),int(*)[3]> << "\n";
    std::cout << std::is_same_v< decltype(&arr[0]), int* > << "\n";
    make_it_decay(arr);
}

output:

1
1
1
1
1

我使用 decltype 来推断某些表达式的类型,并使用 std::is_same_v 来查看表达式是否属于同一类型。

arrint[3] 类型。它是一个数组。它不是指针。

&arr是数组的地址。它是一个指向具有三个元素的数组的指针,a int(*)[3].

&arr[0] 尽管它与 &arr 具有相同的值但类型不同。它是一个指向 int 的指针,一个 int*.

当我们将 arr 传递给函数时,它会衰减为指向数组第一个元素的指针。而我们可以看到函数x里面是int*.


现在回答你的问题...

上面我试图说明当你写 std::cout << arr 时会发生什么。指针是不同的,因为......好数组不是指针。

std::cout << ptr;  // prints the value ptr
std::cout << &ptr; // prints the address of ptr

也许一些形象化的帮助。当递增指针时,类型的差异变得最明显

 -------------------
 | arr             |
 -------------------
 |  1  |  2  |  3  |
 -------------------
   ^       ^         ^
   &arr    |         &arr + 1 
   &arr[0] |
           &arr[0] + 1

array's name is a pointer to the first value in the array

以上说法在技术上是不正确的。发生的情况是,在许多情况下,由于 类型衰减 ,数组 衰减 指向指向其第一个元素的指针。这意味着,在您的示例中,当您编写 std::cout << arr 时,有一个 隐式 array-to-pointer 转换 转换了类型 [=12] 的数组 arr =] 指向其第一个元素的指针,类型为 int*.

备注

另请注意,即使衰减指针和数组地址都具有相同的值,但它们的类型不同。衰减指针的类型为 int*&arr 的类型是 int (*)[3].