理解数组和指针之间的关系

Understanding relationship between arrays and pointers

我最近在读 T*T[size] 之间的区别,T 是类型,这让我很好奇,所以我在玩它。

int main()
{
    int a[10];
    using int10arrayPtr_t = int(*)[10];
    int10arrayPtr_t acopy = a;
}

在上面的代码中,int10array_t acopy = a;是错误消息

error C2440: 'initializing': 
cannot convert from 'int [10]' to 'int10array_t'

这编译:

int main()
{
    int a[10];
    using int10arrayPtr_t = int*;
    int10arrayPtr_t acopy = a;
}

类型 int(*)[10] 不是比 int* 更接近 int a[10]; 的类型吗?那么为什么不允许第一种情况呢?

您需要明确地获取地址,例如

int10arrayPtr_t acopy = &a; // acopy is a pointer to array containing 10 ints
//                      ^

第二种情况有效,因为数组可以 decay 指向指针,对于 a,它可以隐式转换为 int*,而 acopy 是指向 int(注意它不是指向数组的指针)。

在您的第一个示例中,符号 int10arrayPtr_t 是“指向 10 整数数组的指针”的别名。在您的第二个示例中,相同的符号是“指向 单个整数 的指针”的别名。那是完全不同的事情。

此外,数组确实会衰减到指向其第一个元素的指针,但它是指向数组中单个元素的指针。 IE。普通 a 将衰减为 &a[0],类型为 int*。要获得指向数组的指针,您需要对整个数组使用 pointer-to 运算符 &,如 &a.

在极少数情况下,表达式中使用的数组指示符会隐式转换为指向其第一个元素的指针。

所以如果你有一个数组

T a[N];

那你可以写

T *p = a;

因为隐式转换,上面的声明等同于

T *p = &a[0];

如果您将运算符 & 的地址应用于数组,那么您将获得一个取消引用的指针,您将获得原始对象。

例如

T a[N];
T ( *p )[N] = &a;

std::cout << sizeof( *p )  << '\n';

输出语句会给出数组a的大小。

这里有一个演示程序。

#include <iostream>
#include <iomanip>
#include <type_traits>

int main()
{
    const size_t N = 10;
    using T = int;

    T a[N];

    T *p = a;

    std::cout << "std::is_same_v<T &, decltype( *p )> is "
        << std::boolalpha << std::is_same_v<T &, decltype( *p )>
        << '\n';

    std::cout << "sizeof( *p ) = " << sizeof( *p ) << '\n';

    T( *q )[N] = &a;

    std::cout << "std::is_same_v<T ( & )[N], decltype( *q )> is "
        << std::boolalpha << std::is_same_v<T ( & )[N], decltype( *q )>
        << '\n';

    std::cout << "sizeof( *q ) = " << sizeof( *q ) << '\n';
}

程序输出为

std::is_same_v<T &, decltype( *p )> is true
sizeof( *p ) = 4
std::is_same_v<T ( & )[N], decltype( *q )> is true
sizeof( *q ) = 40