我想知道为什么在将多维数组传递到函数时可以省略最左边的索引?为什么不是省略多个索引?如果省略一个索引,编译器如何确定大小?
我想知道为什么在将多维数组传递到函数时可以省略最左边的索引?为什么不是省略多个索引?如果省略一个索引,编译器如何确定大小?
其他答案介绍了C标准如何处理数组到指针的转换以及这如何影响函数声明,但我觉得他们没有深入探讨 为什么,所以在这里我来说明一下...
在C中,数组表示内存中紧密打包的元素。
A -> _ _ _ _ _ _ ...
i: 0 1 2 3 4 5 ...
在上面的例子中,每个数组元素都是1 _
宽度。要找到第i个元素,我们需要转到第i个地址。(请注意,这里最左边的维度(大小)并不重要)B -> [_ _ _][_ _ _][_ _ _][_ _ _]...
i: 0 0 0 1 1 1 2 2 2 3 3 3
j: 0 1 2 0 1 2 0 1 2 0 1 2
^first row ^third row
为了找到A[i][j]
的偏移量,我们需要跳过i行(3*i)和j个元素->(3*i+j)。请注意,这里也不需要第一维的大小。int sum(int arr[10]){
int s = 0, i;
for(i=0; i<10; i++){
s += arr[i];
}
return s;
}
当您可以使用以下方法时:
int sum(int arr[], int n){
int s = 0, i;
for(i=0; i<n; i++){
s += arr[i];
}
return s;
}
对于省略多个维度而言,当使用正常的多维数组时是不可能实现的(因为您需要知道每一维度的大小来确定第一行在哪里结束以及第二行在哪里开始)。然而,如果您愿意为临时空间花费一些额外的空间,那么完全可以使用指向指针的指针实现: http://www.eskimo.com/~scs/cclass/int/sx9b.html
在声明中
实际上,你不能完全省略最右边或最左边的维度。
但是,如果你有一个初始化器,那么最左边的维度可以为你推导出来。
在函数参数列表中
当你通过值将数组传递到函数中时,实际上你传递的是指向该数组第一个元素的指针。是的,从语法上看,它看起来像是你在传递一个数组,但实际上不是这样。
考虑以下例子:
void f(int ar[3])
void f(int ar[])
这两种语法是等价的,但容易让人感到困惑:
void f(int* ar)
void f(int ar[][3])
void f(int (*ar)[3])
int (*)[3]
是指向您的数组第一个元素(指向 int[3]
)的指针类型。
总之,不要过于关注类似[]
的数组语法;它并不能真正代表发生了什么。
int ar[]
时;然而,这与声明无关。 :) - Lightness Races in Orbitsizeof
或一元&
运算符的操作数,或者是在声明中用于初始化数组的字符串字面值,否则类型为"N个元素的T
数组"的表达式将被隐式转换为"指向T
的指针"类型,并将计算为数组中第一个元素的地址。int arr[10] = {0,1,2,3,4,5,6,7,8,9};
foo(arr);
arr
作为参数传递给foo
。由于arr
不是sizeof
或&
的操作数,因此它的类型会隐式转换为“指向int
的指针”,而不是一个数组。因此,我们传递给foo
的是一个指针值,而不是一个数组。
实际上,在函数参数声明中,T a[]
和T a[N]
是T *a
的同义词;所有三个声明都将a
声明为指向T
的指针,而不是T
的数组。
我们可以将foo
的原型定义写成:
void foo(int *a) // <- foo receives a pointer to int, not an array
或者
void foo(int a[]) // <-- a[] is a synonym for *a
这两个表达式的意思相同,都将a
声明为指向整数的指针。
现在让我们看一下多维数组。假设有以下代码:
int arr[10][20];
foo(arr);
arr
的类型为“包含10个20元素的数组,其中每个元素都是一个int
数组”。根据上述规则,它将隐式转换为“指向20个int
元素的数组的指针”。因此,foo
的原型定义可以写成:void foo(int (*a)[20]) // <-- foo receives a pointer to an array, not an array of arrays
或者
void foo(int a[][20]) // <-- a[][20] is a synonym for (*a)[20]
同样地,两者都将a
声明为一个指针,而不是一个数组。
这就是为什么在函数参数声明中可以省略最左边的(唯一的)数组索引。