2017-04-24 134 views
-5
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警告日志。这些C函数参数类型有什么区别?

+0

'int **'是指向'int'的指针。 'int(*)[3]'是指向“int”数组的指针。两者不同,不可互换。 – ameyCU

+1

参见[cdecl.org](https://cdecl.org/?q=void+i%28int+%28*%29%5B%5D%29%3Bhttps://cdecl.org/?q=void+i %28int +%28 *%29%5B%5D%29%3B) – Garf365

+2

[C指针指向数组/指针消除歧义指针]的可能重复(http://stackoverflow.com/questions/859634/c-pointer-to-数组指针 - 消除歧义) –

回答

1

首先,让我们分析哪些声明实际上是等价的,因为示例代码中有很多冗余。

例如,这三个声明都意味着同样的事情编译器:

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 s。你可以很容易地用a[y][x]索引它,因为当你说a[y]时,编译器知道这些行是三个整数的数组,并且会相应地计算出偏移量。