對於指針,我對使用char **或char *或* array的聲明和函數參數感到困惑[ n]等。如果一個函數接受一個(* array [n])參數,我會傳遞一個**類型嗎?C/C++中的指針/數組語法(char ** p,* p [n])
我嘗試使用左右規則並知道p是指向char(char ** p)的指針的指針,p是n個指針(* p [n])的數組,但有人說* p [n]和** p基本上是等價的。真的嗎?
對於指針,我對使用char **或char *或* array的聲明和函數參數感到困惑[ n]等。如果一個函數接受一個(* array [n])參數,我會傳遞一個**類型嗎?C/C++中的指針/數組語法(char ** p,* p [n])
我嘗試使用左右規則並知道p是指向char(char ** p)的指針的指針,p是n個指針(* p [n])的數組,但有人說* p [n]和** p基本上是等價的。真的嗎?
閱讀C宣言(這是與*和[]變量的一部分)是相當細微的。有一些網站與提示:
一個char**
是一個指向(可能是多個)指針(S)到(可能是多個)字符(S)。例如,它可能是一個指向字符串指針的指針,或者是一個指向字符串指針數組的指針。
A char*[]
是指向char的指針數組。當你有一個把它作爲參數的函數時,C編譯器會將它「衰減」爲char**
。這隻發生在第一層...因此,舉一個複雜的例子,char*[4][]
變成char*(*)[4]
。閱讀上面的鏈接,以便了解這意味着什麼。
或者你可以做一個(非常合理的)事情,並做一堆typedefs。我不這樣做,但直到你擅長閱讀宣告者,這是一個好主意。
typedef char * stringp;
void func(stringp array[]) { ... }
static stringp FOUR_STRINGS[4] = { ... };
如果n==0
那麼它們引用相同的內存。數組索引基本上是一個指針加偏移量。 *(p[n])
將與**(p+n)
相同。你可以親眼看到C中的這個簡單,因爲array[4]
和4[array]
會給你同樣的東西。
在正確的上下文(即,參數的函數),則下面的聲明是等價的:
int main(int argc, char *argv[]);
int main(int argc, char **argv);
int main(int argc, char *argv[12]); // Very aconventional!
類似的註釋適用於函數定義(其具有嵌段包含在括號中分號的地方)。
在任何其他情況下,符號之間存在重要差異。例如:
extern char *list1[];
extern char **list2;
extern char *list3[12];
第一個表示某處存在一個包含'char *'值的不確定大小的數組。第二個說某處 - 可能在這裏 - 有一個包含指向字符指針的值的單個值。第三個人說,在某個地方 - 可能在這裏 - 有12個字符指針的數組。
但是,所有三個列表都可以以相同的方式引用 - 假設它們實際上已經被定義和初始化。
list1[0][0] = '1';
list2[0][0] = '2';
list3[0][0] = '3';
此外,如果將它們傳遞到這樣的功能:
function(list1, list2, list3);
則該函數可以聲明爲:
void function(char **list1, char **list2, char **list3);
的陣列(list1的,項目list3)從衰減該數組指向數組的第一個元素;當然,list2已經是一個指向指針的指針了。
void otherfunction(char *list[12])
{
...
}
的C編譯器不把該聲明的任何不同於:
void otherfunction(char **list)
{
...
}
或
void otherfunction(char *list[])
{
...
}
特別
一個詳細的功能,如注意,它沒有進行數組邊界檢查,就功能而言,12也可能不存在。
C99引入VLA(可變長度數組)類型,並且還引入了「靜態」和在陣列邊界的尺寸的符號。您需要閱讀標準以充分理解這些標準。
只需在下面的函數中說數組的大小確實很重要,並且在運行時確定。通常情況下,二維數組除了第一個維外需要指定所有維。
void vla_function(size_t m, int vla[m][m]);
從標準引用(節6.7.5.3):
void f(double (* restrict a)[5]);
void f(double a[restrict][5]);
void f(double a[restrict 3][5]);
void f(double a[restrict static 3][5]);
(注意最後聲明還指定對應於在至f的任何呼叫的參數必須是 非空指針指向至少三個數組中的第一個至少三個數組,其他則不指定)
此外,如果您不是唯一閱讀代碼的人,那麼額外的typedef對其他人的理智也是有益的 - 但當然,不要過分地把它當作相關信息的混亂和分裂(必須結合來自信息源中許多地方的信息來解碼一個結構的含義)也是可讀性。 – Steve314 2010-02-21 09:26:27