這裡說的聲明,不光适用于C/C++,其他的一些語言也能适用。 與java和C#等不同,聲明和定義在C/C++中有着比較明顯的差別:聲明僅僅是介紹名字(introduce names),而定義則會為該名字配置設定相應的空間。打個通俗的比喻:聲明就是你在談話中提到某個人的名字,而定義就是把你提到的這個人帶到談話的人群中來,讓大家見識一下他/她是什麼樣子。 這裡主要介紹聲明。 在C中,聲明的形式為(dcl是declaration的簡寫): dcl: optional *'s direct-dcl(含有可選"*"的direct-dcl) direct-dcl name (dcl) direct-dcl() direct-dcl[optional size] 根據該規則進行逆向解析,就可以得到正确的聲明。簡化一下:“TypeName Declarator;”其中,Declarator就是聲明中的那個名字。當你遇到任何你不能了解的聲明時,這個法則就是救命稻草。最簡單的例子: int aInt; 這裡,int是TypeName,aInt是Declarator。 再說明一下結合緊密度。在聲明/定義變量時,可以使用一些修飾比如“*”,“[]”,“()”等。“()”(非函數聲明中的“()”)具有最高的緊密度,其次才是函數和數組的“()”和“[]”。 沒有“*”的聲明稱為直接聲明(direct-dcl),而有“*”稱為聲明(dcl)。直接聲明要比聲明結合的緊。分解聲明時,先讀出結合緊的。在這裡,我把direct-dcl稱為更緊的結合,它比dcl結合得緊。 最後,需要你用英語來讀出這個聲明。對于“[]”,應該讀成array of。 對于複雜的定義,可以将其分解。比如“T (*p)()”可以分解成“T D1()”,D1讀作:function returning T。其中D1是*p。那麼該聲明應該讀成:p is a poniter to。二者合在一起,就變成了p is a pointer to function returning T,即:p是指向傳回T類對象的函數的指針。 再看一個稍微複雜的示例: T (*pfa[])(); 根據dcl和direct-dcl,可以分解成T1 D1(因為結合緊密度),T1, 也就是T (),那麼應該讀作: D1 is function returning T。 D1又可以寫成T2 D2,其中T2是T1 [],可以分解成T1 D2[],讀作: array of D2 function returning T。 D2是指針,讀作:pointers to。那麼整個“T (*pfa[])();”應該讀作: pfa is an array of pointers to function returning T,即:pfa是個存放指向傳回T類對象函數的指針的數組。 換種方式看,在這個例子中,pfa是名字,T(*[])()是類型。将(*pfa[])視為一體(direct-dcl),稱為D1,那麼可以寫成T D1(),function returning object of T。在D1中,将*pfa視為一體(dcl),稱為D2,那麼*pfa[]應該是D2[](direct-dcl),array of D2。合起來就是array of D2 function returning object of T。D2是*pfa(dcl),替換到前面這句話,結果就是array of pointers to function returning object of T。 有了這些說明,可以試着做一下下面的題,看看自己是否真的了解了: char **argv
argv: pointer to pointer to char
int (*daytab)[13]
daytab: pointer to array[13] of int
int *daytab[13]
daytab: array[13] of pointer to int
void *comp()
comp: function returning pointer to void
void (*comp)()
comp: pointer to function returning void
char (*(*x())[])()
x: function returning pointer to array[] of
pointer to function returning char
char (*(*x[3])())[5]
x: array[3] of pointer to function returning
pointer to array[5] of char 有了這個,就很容易了解下面這兩個typedef: typedef void (*disp)(int); typedef void (*signal(int, disp))(int); 在C++中,規則比C要複雜一些。不過,基本思想保持不變,按照C的原則來了解複雜的聲明,基本上就能滿足要求了。沒有在這裡列出C++的規則一方面是因為太廣,不能覆寫全;另一個原因就是,按照C的規則來就足夠了,畢竟C++要與C相容。 這裡讨論的僅僅是聲明,不涉及到類型的signature,是以相對來說還是比較簡單的。 參考: The C programming Language, by Brian W. Kernighan and Dennis M. Ritchie The C++ programming Language, by Bjarne Stroustup Copyleft (C) 2007-2009 raof01. 本文可以用于除商業外的所有用途。此處“用途”包括(但不限于)拷貝/翻譯(部分或全部),不包括根據本文描述來産生代碼及思想。若用于非商業,請保留此 權利聲明,并标明文章原始位址和作者資訊;若要用于商業,請與作者聯系([email protected]),否則作者将使用法律來保證權利。 |