2017-04-24 131 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]時,編譯器知道這些行是三個整數的數組,並且會相應地計算出偏移量。