2D数组不会衰减到指针指针

到目前为止,我非常肯定

int arr[4][5]; 

然后arr将衰减到指针指针。

但这个链接certificate我错了。

我不知道如何得到arr指针指针,但对我来说这似乎很明显。 因为arr[i]将是一个指针,因此arr应该是指向指针的指针。

我错过了什么。

你错过了很多:)

为了避免另一面文本,我将链接到我今天早些时候写的解释多维数组的答案 。

考虑到这一点, arr是一个包含4个元素的1-D数组,每个元素都是5个int的数组。 当在&arrsizeof arr以外的表达式中使用时,这会衰减为&arr[0] 。 但是&arr[0]什么? 它是一个指针,重要的是一个右值。

由于&arr[0]是一个指针,它不能进一步衰减。 (数组衰减,指针没有)。 此外,它是一个左值。 即使它可以衰减成指针,指针指向哪里? 你不能指向右值。 (什么是&(x+y) ?)

另一种看待它的方法是记住int arr[4][5]; 是一个20个int的连续集团,在编译器的脑海中分为4批5,但在运行时内存中没有特殊标记。

如果有“双重衰变”那么int **指向什么? 根据定义,它必须指向int * 。 但内存中的那个是int * ? 在发生这种情况时,内存中肯定没有一堆指针。

一个简单的规则是:

对表达式中出现的array-of-T类型的对象的引用将(有三个例外)衰减为指向其第一个元素指针 ; 结果指针的类型是指向T的指针。

处理1D数组时,数组名称在传递给函数时会转换为指向第一个元素的指针。
2D数组可以被认为是数组数组 。 在这种情况下int arr[4][5]; ,您可以将arr[]视为数组名称,并在传递给函数时转换为指向数组arr的第一个元素的指针。 由于arr第一个元素是一个数组,因此arr[i]是指向数组第i行的指针,并且是指向5个int的数组的指针类型。

通常,2-dim数组实现为指针数组(在某种意义上,它是指向指针的指针…指向数组中第一个元素(即指针)的指针)当您指定时第一个索引(即arr[x] ),它索引到指针数组并给出指向第x行的指针。 第二个索引(即arr[x][y] )给出该行中的y -th int

对于静态声明的数组(如在您的示例中),实际存储在单个块中分配…在您的示例中,作为单个连续的20个整数块(大多数平台上为80个字节)。 在这种情况下,没有指针数组,编译器只是执行适当的算术来寻址数组的正确元素。 具体而言, arr[x][y]相当于*(arr + x * 5 + y) 。 这种自动调整的算法只发生在数组的原始范围内…如果将数组传递给函数,则尺寸信息会丢失(就像1-dim数组的尺寸丢失一样),而且你有明确地进行数组索引计算。

要避免这种情况,请不要将数组声明为静态,而是将其声明为指针数组,每个指针都指向1-dim数组,例如:

 int arr0[5]; int arr1[5]; int arr2[5]; int arr3[5]; int* arr[4] = { arr0, arr1, arr2, arr3 }; 

然后,当您将arr传递给函数时,您也可以将其作为函数内的2-dim数组来处理。