我在 C 函数的形式参数中阅读了这两种不同类型的多维数组声明。
int c[][10];
int (*c)[10];
这两个怎么一样?我没有感觉到它。谁能用一些例子来解释第二个试图做什么?抱歉,如果以前有人问过这个问题。如果有的话,请将我重定向到副本。
我在 C 函数的形式参数中阅读了这两种不同类型的多维数组声明。
int c[][10];
int (*c)[10];
这两个怎么一样?我没有感觉到它。谁能用一些例子来解释第二个试图做什么?抱歉,如果以前有人问过这个问题。如果有的话,请将我重定向到副本。
作为函数参数,int* c
和int c[]
甚至int c[7]
是相同的。请参阅C 常见问题解答。
该[10]
部分仅告诉编译器如何进行算术以访问数组中的元素 - 例如c[3][5]
。这两个声明都针对一个多维数组,其第二维(就编译器而言,在此函数内部)大小为 10。
例子:
#include <stdio.h>
int sum_all(int c[][2], int len) {
int res = 0, i ,j;
for (i=0; i < len; i++)
for (j=0; j < 2; j++)
res += c[i][j];
return res;
}
int main() {
int a[3][2] = { { 1, 2}, {3, 4}, {5, 6} };
printf("sum is %d\n", sum_all(a, 3));
return 0;
}
请注意,在此示例中,未检查数组的大小为 2。我们可以传递一个一维数组。编译器不在乎;我们只告诉他如何访问这个数组中的元素。
N1570:
6.7.6.3 函数声明符(包括原型)
......
7 将参数声明为“类型数组”应调整为“ 类型限定符”,其中类型限定符(如果有)是指定的在数组类型派生的[
and中。]
如果关键字static
也出现在数组类型派生的[
and]
中,那么对于函数的每次调用,对应的实际参数的值应提供对数组的第一个元素的访问,该数组的元素至少与大小指定的一样多表达。
因此,在函数参数声明的上下文中,T a[N]
和T a[]
都等价于T *a
; 这三个都声明a
为指向T
. 在这种特殊情况下,T
是“10 元素数组int
”。
这与以下内容密切相关:
6.3.2.1 左值、数组和函数指示符
...
3 除非它是运算sizeof
符、运算符_Alignof
或一元&
运算符的操作数,或者是用于初始化数组的字符串字面量,否则为 '' 类型的表达式'' 类型的数组被转换为类型为 ''类型的指针的表达式,该指针指向数组对象的初始元素,而不是左值。如果数组对象具有寄存器存储类,则行为未定义。
假设您有一个声明为的数组
int arr[5][10];
当您将数组表达式arr
传递给函数时,例如
foo( arr );
数组表达式arr
从类型“10 元素数组的 5 元素数组int
”类型转换为“指向 10 元素数组的指针”类型int
,并且该指针值是传递给函数的值。所以你的函数原型foo
将读作
void foo( int (*c)[10] )
或者
void foo( int c[][10] )
甚至
void foo( int c[5][10] )
但在所有三种情况下,c
都是指向数组的指针,而不是二维数组。
考虑当您定义int c[5][10]
然后传递c
给例程时会发生什么。该数组c
将自动转换为指向其第一个元素的指针,该元素是 10 的数组int
。
因此语言设计者对其进行了安排,以便当您使用 声明参数时c[][10]
,它会自动调整以匹配将要发生的转换。编译器将数组类型的参数更改为int
指向数组的指针类型的参数int
。