理解数组和指针之间的关系
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
我最近在读 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