如何理解复杂的数组声明指针,以及

how to Understand complicated array declaration pointers, and &

本文关键字:指针 以及 声明 数组 何理解 复杂      更新时间:2023-10-16

有两行代码:

int (*parry)[10]   = &arr   // Line # 1
int *(&arrRef)[10] = ptrs   // Line # 2

第1行:

parry是指向大小为10的int数组的指针。
那么它的意思是:

  • parray[1]指向arr地址,
  • parray[2]指向arr地址
  • parray[10]指向地址还是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个指针。arrRefptrs引用。
那么它的意思是:

  • 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++中都是隐式的。&符号仅用于表示声明中的引用(可能有些令人困惑,因为在表达式中它用于接受地址)。但是,如果您将声明中的&视为*的替代品,以表示引用而不是指针,则应该仍然能够解析任何声明。

相关文章: