如何理解复杂的数组声明指针,以及
how to Understand complicated array declaration pointers, and &
有两行代码:
int (*parry)[10] = &arr // Line # 1
int *(&arrRef)[10] = ptrs // Line # 2
第1行:
parry
是指向大小为10的int
数组的指针。
那么它的意思是:
-
parray[1]
指向arr
地址, - …
-
parray[10]
指向地址还是arr
?
parray[2]
指向arr
地址何时使用Line # 1
?
解决方案:
#include <iostream>
int main(
{
int arr[10] = { 3, 54 };
int (*parry)[10] = &arr;
std::cout << (*parry)[0] << " " << (*parry)[1] << " " << (*parry)[3] << " " << parry[4] << std::endl;
return 0;
}
输出:3, 54,0,索引为4的arr十六进制地址
看起来parry[0]
内部是一个指向与索引关联的arr
的指针。所以,parry[0]
-> arr[0]
。
第2行:
arrRef
是对int
数组的引用,该数组大小为10个指针。arrRef
被ptrs
引用。
那么它的意思是:
-
arry[1]
是int
指针?… -
arry[10]
是一个int
指针?
这个可以用在什么例子中?
如果有疑问,请参见顺时针/螺旋规则。
int (*parry)[10] = &arr;
parry
是一个指针,指向一个包含10个int
的数组。
int *(&arrRef)[10] = ptrs;
arrRef
是一个包含10个int指针的数组的引用。
的例子:
int main()
{
int arr[10];
int* ptrs[10];
int (*parry)[10] = &arr;
int *(&arrRef)[10] = ptrs;
}
现在我已经清理了你的问题,我可以看出这不是我最初的想法。你说:
parray是指向大小为10的整型数组的指针
很明显你已经弄清楚顺时针/螺旋/cdecl的东西了。
所以这意味着:…数组[10]指向arr
的地址
首先,c++中的数组从0开始索引,所以如果有10个元素,可以访问arr[0] .. arr[9]
;arr[10]
将是第11位,因此是越界的。
现在,让我们把你的句子拆开:
parray
是一个指针
对,它不是数组,它是指针。现在,让我们考虑一下它是什么指针:
一个大小为10的int数组
好的,如果指向,那么*parray
必须是原始数组的引用。
那么,(*parray)[0]
是数组的第一个元素,等等。
请注意,您可以很容易地测试您对所有这些的直觉,只需打印出来,看看您得到什么。您将看到指针,并能够比较地址,或者您将看到整数值,或者您将获得(希望提供信息)编译错误。试试吧!
哦,:
何时使用第一行?
一般来说,只有在您需要重新安置它时才会这样。例如,如果您想根据某些逻辑从两个不同的数组中选择一个,然后……
接下来,你说
arrRef是对一个大小为10个指针的int数组的引用。
正确!
arref被ptrs引用
不,arrRef
指的是数组,数组的大小为10,其中的10个元素是指向整型的指针。注意这与第一个数组的类型不同!
由于引用可以与它们所引用的对象使用相同的语法,因此我们可以使用arrRef
作为数组。
因此,arrRef[0]
是数组的第一个元素,它是一个指向整型的指针。
这个可以用在什么例子中?
使用引用到数组的唯一常见原因是避免指针衰减,允许模板推断元素的数量。
我认为在这个声明中
//line1// int (*parry)[10] = $arr
^^^ ^^
有一个错字
一定有
//line1// int (*parry)[10] = &arr;
^^^ ^^
假定arr
是类型为int[10]
的数组。例如
int arr[10];
和这个声明
int (*parry)[10] = &arr;
声明一个指向整个数组的指针。
对于这个声明
//line2// int *(&arrRef)[10] = ptrs;
^^^
则假定ptrs
是类型为int *[10]
的数组,即该数组的元素类型为int *
。它们是指针。
和这个声明
int * (&arrRef)[10] = ptrs;
声明了对这个数组的引用。引用实际上是数组的别名。
在c++ 2014中,可以更简单地定义对数组的引用。
例如decltype( auto )arrRef = ( ptrs );
下面是一个示范程序
#include <iostream>
int main()
{
int a[10];
decltype( auto )ra = ( a );
std::cout << sizeof( a ) << std::endl;
std::cout << sizeof( ra ) << std::endl;
ra[0] = 10;
std::cout << a[0] << std::endl;
std::cout << ra[0] << std::endl;
}
程序输出为
40
40
10
10
对于解析C声明来说,记住这一点很有价值,用Kernighan和Ritchie的话来说,"语法是试图使声明和使用一致"(K&R, TCPL, 5.12)。换句话说,您可以将声明视为表达式,并简单地以适当的顺序应用操作符。这将显示声明的标识符必须具有的类型。
例如,在int (*parry)[10]
中,首先应用*
操作符,因为它在括号中。这表明parray
是一个指针。然后应用[]
操作符,表明解引用的结果是一个数组;10
表示元素个数。获得的元素是int类型的。总结:parray
是一个指向int型数组的指针。
引用声明不能以这种方式解决,因为实际上没有创建引用或解引用的操作符;这两个操作在c++中都是隐式的。&
符号仅用于表示声明中的引用(可能有些令人困惑,因为在表达式中它用于接受地址)。但是,如果您将声明中的&
视为*
的替代品,以表示引用而不是指针,则应该仍然能够解析任何声明。
- 非类型指针和引用模板参数,以及在编译时如何/为什么解析它们.c++
- 我可以有一个 ELI5 作为参考和指针以及何时使用它们吗?
- 是否可以使用非常量指针调用非常量函数,以及当两个unique_ptrs指向同一个对象时程序的行为方式?
- 使用指针向量(带代码)C++(以及对其使用的便利性的怀疑)时出现问题
- SFINAE - 检测类型 T 是指针、数组还是带有随机访问运算符的容器,以及给定的值类型
- 作为模板参数的成员函数指针在继承的成员函数上失败,如何以及为什么?
- 可变引用以及指针如何与内存相互作用
- 这是删除基类指针的内存泄漏吗,以及如何使其正确
- 返回指针的语句 - 解释它是如何工作的以及为什么
- 涉及继承,指针对象的交易以及何时进行的问题
- 使用删除与智能指针释放内存以及释放内存的正确方法
- 关于Lambdas,转换以功能指针以及私人数据成员的可见性
- C++ - 函数中的局部指针变量具有什么类型的存储持续时间以及它们存储在哪里?
- 构造函数、析构函数和指针(以及向量、数组和删除等等)
- c++中的原子指针以及在线程之间传递对象
- 分段错误和char指针以及int ponter
- Visual Studio如何处理已删除的指针以及原因
- 有关指针以及什么是/不是指针的问题
- 将指针赋值给指针(以及将指针传递给类)时使用delete的混淆
- 我想存储函数的void指针以及它们的类型