这些 C 函数参数类型有什么区别?
What is the difference in these C function argument type?
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;
}
这些C函数参数类型有什么区别?
指针数组和二维数组之间有很多混淆
注释是 GCC 警告日志。
首先,让我们弄清楚哪些声明实际上是等价的,因为您的示例代码中有很多冗余。
例如,这三个声明对编译器的意义完全相同:
void f(int **a) {}
void g(int *a[]) {}
void h(int *a[3]) {}
任何数组类型的函数参数都会衰减为指向数组第一个元素的指针,因此 int **a
是所有三个函数参数实际使用的类型。
同样,这两个声明是相同的:
void j(int (*a)[3]) {}
void k(int a[][3]) {}
这里,参数的有效类型是int (*a)[3]
.
这只剩下三个不同的变体:
void f(int **a) {}
void i(int (*a)[]) {}
void j(int (*a)[3]) {}
第一个是指向int
的指针。这通常用于将二维数组作为指向线数组指针数组的指针传递。索引工作正常,但它需要正确设置额外的指针数组。
第二个几乎无法使用:它定义了一个指向数组的指针,其大小未知。因此,您无法使用 a[y][x]
对数组进行索引,因为行的大小未知,因此无法计算行 y
的偏移量。
最后一个传递一个二维数组,宽度为三个int
。您可以使用 a[y][x]
轻松对其进行索引,因为当您说 a[y]
时,编译器知道这些行是三个整数的数组,并将相应地计算偏移量。
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;
}
这些C函数参数类型有什么区别? 指针数组和二维数组之间有很多混淆 注释是 GCC 警告日志。
首先,让我们弄清楚哪些声明实际上是等价的,因为您的示例代码中有很多冗余。
例如,这三个声明对编译器的意义完全相同:
void f(int **a) {}
void g(int *a[]) {}
void h(int *a[3]) {}
任何数组类型的函数参数都会衰减为指向数组第一个元素的指针,因此 int **a
是所有三个函数参数实际使用的类型。
同样,这两个声明是相同的:
void j(int (*a)[3]) {}
void k(int a[][3]) {}
这里,参数的有效类型是int (*a)[3]
.
这只剩下三个不同的变体:
void f(int **a) {}
void i(int (*a)[]) {}
void j(int (*a)[3]) {}
第一个是指向int
的指针。这通常用于将二维数组作为指向线数组指针数组的指针传递。索引工作正常,但它需要正确设置额外的指针数组。
第二个几乎无法使用:它定义了一个指向数组的指针,其大小未知。因此,您无法使用 a[y][x]
对数组进行索引,因为行的大小未知,因此无法计算行 y
的偏移量。
最后一个传递一个二维数组,宽度为三个int
。您可以使用 a[y][x]
轻松对其进行索引,因为当您说 a[y]
时,编译器知道这些行是三个整数的数组,并将相应地计算偏移量。