这些C函数参数类型的区别是什么?
这些C函数参数类型的区别是什么? 指针数组和二维数组之间有很多混淆这些C函数参数类型的区别是什么?,c,gcc,ansi-c,C,Gcc,Ansi C,这些C函数参数类型的区别是什么? 指针数组和二维数组之间有很多混淆 注释是GCC警告日志。首先,让我们整理一下哪些声明实际上是等效的,因为示例代码中存在大量冗余 例如,这三个声明对编译器的意义完全相同: void f(int **); void g(int *[]); void h(int *[3]); void i(int (*)[]); void j(int (*)[3]); void k(int [][3]); void f(int **a) {} void g(int *a[]) {}
注释是GCC警告日志。首先,让我们整理一下哪些声明实际上是等效的,因为示例代码中存在大量冗余 例如,这三个声明对编译器的意义完全相同:
void f(int **);
void g(int *[]);
void h(int *[3]);
void i(int (*)[]);
void j(int (*)[3]);
void k(int [][3]);
void f(int **a) {}
void g(int *a[]) {}
void h(int *a[3]) {}
void i(int (*a)[]) {}
void j(int (*a)[3]) {}
void k(int a[][3]) {}
int main(void) {
int a[3] = {1,2,3};
int b[2] = {4,5};
int *c[2] = {a, b};
int d[2][3] = {{1,2,3},{4,5,6}};
f(c);
f(d); // note: expected ‘int **’ but argument is of type ‘int (*)[3]’
g(c);
g(d); // note: expected ‘int **’ but argument is of type ‘int (*)[3]’
h(c);
h(d); // note: expected ‘int **’ but argument is of type ‘int (*)[3]’
i(c); // note: expected ‘int (*)[]’ but argument is of type ‘int **’
i(d);
j(c); // note: expected ‘int (*)[3]’ but argument is of type ‘int **’
j(d);
k(c); // note: expected ‘int (*)[3]’ but argument is of type ‘int **’
k(d);
return 0;
}
任何数组类型的函数参数都会衰减为指向数组第一个元素的指针,因此int**a
是实际用于所有三个函数参数的类型
同样,这两个声明是相同的:
void f(int **a) {}
void g(int *a[]) {}
void h(int *a[3]) {}
这里,参数的有效类型是int(*a)[3]
这只剩下三种不同的变体:
void j(int (*a)[3]) {}
void k(int a[][3]) {}
第一个是指向int
的指针。这通常用于将2D数组作为指针传递给线数组的指针数组。索引工作正常,但需要正确设置额外的指针数组
第二个几乎不可用:它定义了一个指向数组的指针,数组的大小未知。因此,不能使用a[y][x]
索引到数组中,因为行的大小未知,因此无法计算行y
的偏移量
最后一个通过一个宽度为三
int
s的2D数组。你可以很容易地用a[y][x]
对它进行索引,因为当你说a[y]
时,编译器知道行是三个整数的数组,并会相应地计算偏移量。int**
是指向int
的指针int(*)[3]
是指向int
数组的指针。两者都不同,不能互换。请参阅@WernerHenze的可能重复项。它没有重复,但我没有注意到运算符的优先级,更容易理解这些奇怪的声明。
void f(int **a) {}
void i(int (*a)[]) {}
void j(int (*a)[3]) {}