逗號(hào)運(yùn)算符(Comma Operator)也是一種雙目運(yùn)算符,它的形式是表達(dá)式1, 表達(dá)式2
,兩個(gè)表達(dá)式不要求類(lèi)型一致,左邊的表達(dá)式1先求值,求完了直接把值丟掉,再求右邊表達(dá)式2的值作為整個(gè)表達(dá)式的值。注意,函數(shù)調(diào)用時(shí)各實(shí)參之間也是用逗號(hào)隔開(kāi),這種逗號(hào)是分隔符而不是逗號(hào)運(yùn)算符。但可以這樣使用逗號(hào)運(yùn)算符:
f(a, (t=3, t+2), c)
sizeof
是一個(gè)很特殊的運(yùn)算符,它有兩種形式:“sizeof 表達(dá)式”和“sizeof(類(lèi)型名)”。這個(gè)運(yùn)算符很特殊,“sizeof 表達(dá)式”中的子表達(dá)式并不求值,而只是根據(jù)類(lèi)型轉(zhuǎn)換規(guī)則求得子表達(dá)式的類(lèi)型,然后把這種類(lèi)型所占的字節(jié)數(shù)作為整個(gè)表達(dá)式的值。有些人喜歡寫(xiě)成“sizeof(表達(dá)式)”的形式也可以。
sizeof
運(yùn)算符的結(jié)果是size_t
類(lèi)型的,這個(gè)類(lèi)型定義在stddef.h
頭文件中,不過(guò)你的代碼中只要不出現(xiàn)size_t
這個(gè)類(lèi)型名就不用包含這個(gè)頭文件,比如像上面的例子就不用包含這個(gè)頭文件。C標(biāo)準(zhǔn)規(guī)定size_t
是一種無(wú)符號(hào)整型,編譯器可以用typedef
做一個(gè)類(lèi)型聲明,那么size_t
就代表unsigned long
型。不同平臺(tái)的編譯器可能會(huì)根據(jù)自己平臺(tái)的具體情況定義size_t
所代表的類(lèi)型,比如有的平臺(tái)定義為unsigned long
型,有的平臺(tái)定義為unsigned long long
型,C標(biāo)準(zhǔn)規(guī)定size_t
這個(gè)名字就是為了隱藏這些細(xì)節(jié),使代碼具有可移植性。
typedef用來(lái)聲明一個(gè)別名,typedef后面的語(yǔ)法,是一個(gè)聲明。本來(lái)筆者以為這里不會(huì)產(chǎn)生什么誤解的,但結(jié)果卻出乎意料,產(chǎn)生誤解的人不在少數(shù)。罪魁禍?zhǔn)子质悄切┖θ说慕滩摹T谶@些教材中介紹typedef的時(shí)候通常會(huì)寫(xiě)出如下形式: typedef int PARA; 這種形式跟#define int PARA幾乎一樣,這些教材的宗旨是由淺入深,但實(shí)際做出來(lái)的行為卻是以偏蓋全。的確,這種形式在所有形式中是最簡(jiǎn)單的,但卻沒(méi)有對(duì) typedef進(jìn)一步解釋,使得不少人用#define的思維來(lái)看待typedef,把int與PARA分開(kāi)來(lái)看,int是一部分,PARA是另一部分,但實(shí)際上根本就不是這么一回事。int與PARA是一個(gè)整體!就象int i:聲明一樣是一個(gè)整體聲明,只不過(guò)int i定義了一個(gè)變量,而typedef定義了一個(gè)別名。這些人由于持有這種錯(cuò)誤的觀念,就會(huì)無(wú)法理解如下一些聲明: typedef int a[10]; typedef void (*p)(void); 他們會(huì)以為a[10]是int的別名,(*p)(void)是void的別名,但這樣的別名看起來(lái)又似乎不是合法的名字,于是陷入困惑之中。實(shí)際上,上面的語(yǔ)句把a(bǔ)聲明為具有10個(gè)int元素的數(shù)組的類(lèi)型別名,p是一種函數(shù)指針的類(lèi)型別名。 雖然在功能上,typedef可以看作一個(gè)跟int PARA分離的動(dòng)作,但語(yǔ)法上typedef屬于存儲(chǔ)類(lèi)聲明說(shuō)明符,因此嚴(yán)格來(lái)說(shuō),typedef int PARA整個(gè)是一個(gè)完整的聲明。 定義一個(gè)函數(shù)指針類(lèi)型。 比如原函數(shù)是 void func(void); 那么定義的函數(shù)指針類(lèi)型就是typedef void (*Fun)(void); 然后用此類(lèi)型生成一個(gè)指向函數(shù)的指針: Fun func1; 當(dāng)func1獲取函數(shù)地址之后,那么你就可以向調(diào)用原函數(shù)那樣來(lái)使用這個(gè)函數(shù)指針: func1(void);
下面舉幾個(gè)例子:
typedef struct tagMyStruct
{
int iNum;
long lLength;
} MyStruct;
下一個(gè)
typedef struct tagNode
{
char *pItem;
pNode pNext;
} *pNode;
編譯錯(cuò)誤,C語(yǔ)言當(dāng)然允許在結(jié)構(gòu)中包含指向它自己的指針,我們可以在建立鏈表等數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)上看到無(wú)數(shù)這樣的例子,上述代碼的根本問(wèn)題在于typedef的應(yīng)用。正確的:
typedef struct tagNode
{
char *pItem;
struct tagNode *pNext;
} *pNode;