2013-01-10 117 views
0

編譯:傳遞一個指針的指針用C

#include <stdlib.h> 


void f(int ** v) 
{ 
} 

int main() 
{ 
    int v[2][3]; 
    f(v); 
    return 0; 
} 

失敗:

g.cpp:13:8: error: cannot convert ‘int (*)[3]’ to ‘int**’ for argument ‘1’ to ‘void f(int**)’ 

但通過了以下變化:

#include <stdlib.h> 


void f(int ** v) 
{ 
} 

int main() 
{ 
    int * v[2]; 
    f(v); 
    return 0; 
} 

這在我看來,更深一個數組的維度必須在編譯時解決,有人可以詳細說明它嗎?

+3

前者不是指向指針的指針,而是2D數組(它將衰減爲指向數組的指針)。數組不是指針。 – netcoder

+0

[在C中傳遞多維數組作爲函數參數](http://stackoverflow.com/questions/4051/passing-multidimensional-arrays-as-function-arguments-in-c)或[爲什麼不能我將一個二維數組轉換爲C中的二維指針?](http://stackoverflow.com/questions/8264392/why-cant-i-convert-a-two-dimensional-array-toa-a-二維指針在c),或許多其他。 – netcoder

+1

[我的編譯器抱怨,當我將一個二維數組傳遞給期望指向指針的函數](http://c-faq.com/aryptr/pass2dary.html)爲什麼這個C標記的問題有一個C++例? – effeffe

回答

2

C和C++自動迫使陣列的指針。該錯誤是由於這種強制只發生一次(即僅在第一級)而引起的。這意味着int [10]將被強制爲int *;但int [10][10]最多可以強制爲int *[10]

原因與內存佈局有關。你看,a[i]轉換爲*(a + sizeof(T) * i)如果aT *類型(假設添加指針直接添加沒有縮放);但如果a的類型是T [N],則a[i]轉換爲*(&a[0] + i)。因此,通過取第一個元素的地址,可以將T [N]類型的值強制爲類型T *的值 - 在這種情況下,內存佈局是兼容的。

但是,二維數組a(類型爲T [2] [4])將以與雙指針(T **類型)不同的方式存儲。在第一種情況下,您有四個元素,T [0][0]T [0][3]在內存中放置,然後按T [1][0]T [1][3]等等進行模對齊。在第二種情況下,你只需要一堆指針(至T)一個接一個地排列。在第一種情況下,a[i][j]將降至*(&a[0][0] + sizeof(T) * 4 * i + sizeof(T) * j),而在第二種情況下,它將降至*(*(a + sizeof(T) * i) + sizeof(T) * j)。內存佈局不再兼容。

+0

很好的回答!關於內存佈局的解釋正是我正在尋找的!只要確定它是一個錯字。如果將[i] [j]降低到*(*(a + sizeof(* T)* i)+ sizeof(T)* j)而不是*(*(a + sizeof(T)* i)+ sizeof (T)* j)? –

0

指向int的指針與指向數組的指針不同。

當這樣做v++,編譯器必須被告知,如果由sizeof(int)遞增地址或通過array_length*sizeof(int)