到目前为止,我非常确定
int arr[4][5];
然后arr
会衰减到指针指针。
我不确定我是如何得到arr
指针指针的,但对我来说这似乎很明显。因为arr[i]
将是一个指针,因此arr
应该是指向指针的指针。
我错过了什么。
答案 0 :(得分:3)
是的,你错过了很多:)
为了避免另一面文字,我将链接到解释多维数组的an answer I wrote earlier today。
考虑到这一点,arr
是一个包含4个元素的一维数组,每个元素都是5 int
个数组。
在&arr
或sizeof arr
以外的表达式中使用时,此衰减为&arr[0]
。但是什么是&arr[0]
?它是一个指针,更重要的是一个右值。
由于&arr[0]
是指针,因此无法进一步衰减。 (数组衰减,指针没有)。此外,它是一个左值。即使它可以衰减成指针,指针指向哪里?你不能指向右值。 (什么是&(x+y)
?)
另一种看待它的方法是记住int arr[4][5];
是一个20 int
的连续集团,在编译器的脑海中分为4批5,但在内存中没有特殊标记运行时。
如果有“双重衰变”那么int **
会指向什么?根据定义,它必须指向int *
。但内存中的那个int *
?在发生这种情况时,内存中肯定没有一堆指针。
答案 1 :(得分:1)
一个简单的规则是:
对表达式中出现的array-of-T类型的对象的引用将(有三个例外)衰减到指向其第一个元素的指针;结果指针的类型是指向T的指针。
处理1D数组时,数组名称在传递给函数时转换为指向第一个元素的指针
可以将2D数组视为数组数组。在这种情况下int arr[4][5];
,您可以将arr[]
视为数组名称,并在传递给函数时转换为指向数组arr
的第一个元素的指针。由于arr
的第一个元素是一个数组,arr[i]
是指向数组i
行的指针,其类型为指向5 int
个数组的指针。
答案 2 :(得分:0)
通常,2-dim数组实现为指针数组(在某种意义上,它是指向指针的指针...指向数组中第一个元素(即指针)的指针)你指定第一个索引(即arr[x]
),它索引到指针数组并给出指向x
行的指针。第二个索引(即arr[x][y]
)给出该行中的y
- 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数组进行处理。