最近看了幾天的 K&R 的< C程序設(shè)計語言 >第二版阅茶,當(dāng)讀到的第5.12章的復(fù)雜函數(shù)聲明時扭吁,我感覺腦袋不夠用了谅摄。之前雖然匆匆使用過幾次函數(shù)指針,闽寡。就像快排的一樣。雖說有點難度,但是當(dāng)時還是能看懂的。
快速排序
/* 具體實現(xiàn)參見: < C程序設(shè)計語言 > P103 */
void qsort(void *v[], int left, int right, int (*comp)(void *, void *)) {
// ...
}
int cmp(char* s1, char* s2) {
// ...
}
void swap(void *v[], int i, int j) {
// ...
}
這段代碼里面绸贡,comp
為一個函數(shù)指針捧挺,在使用之前需要使其指向一個函數(shù),就像cmp
函數(shù)摊溶。
int (*comp)(void *, void *); //定義
comp = cmp霞玄; //指向cmp函數(shù)
由于在C語言里面把void*
當(dāng)做通用指針,所以在參數(shù)傳遞上使用了void*
拉岁。以方便在以后需要排序其他類型對象時坷剧,只需要給出比較方法,既cmp
函數(shù)喊暖,就可比較惫企。 但是在進(jìn)行比較的時候得把他轉(zhuǎn)換成原本的類型。書中介紹陵叽,在第一版時狞尔,也用char*
做為通用指針。
復(fù)雜聲明
剛剛看的comp指針可能很容易明白巩掺,下面再看幾個例子
int *day[13];
void *comp();
void (*comp)();
char (*(*x())[])();
char (*(*x[3])())[5];
是不是只能認(rèn)識前三個偏序。不要緊,下面重點來了胖替。
右左法則
右左法則其實并不是C標(biāo)準(zhǔn)里面的內(nèi)容研儒,它是從C標(biāo)準(zhǔn)的聲明規(guī)定中歸納出來的方法。C標(biāo)準(zhǔn)的聲明規(guī)則独令,是用來解決如何創(chuàng)建聲明的端朵,而右左法則是用來解決如何辯識一個聲明的,兩者可以說是相反的记焊。
The right-left rule
: Start reading the declaration from the innermost parentheses, go right, and then go left. When you encounter parentheses, the direction should be reversed. Once everything in the parentheses has been parsed, jump out of it. Continue till the whole declaration has been parsed.
右左法則
:首先從最里面的圓括號看起逸月,然后往右看,再往左看遍膜。每當(dāng)遇到圓括號時碗硬,就應(yīng)該掉轉(zhuǎn)閱讀方向。一旦解析完圓括號里面所有的東西瓢颅,就跳出圓括號恩尾。重復(fù)這個過程直到整個聲明解析完畢。
網(wǎng)上有人說應(yīng)該是未定義的標(biāo)識符開始閱讀挽懦,而不是從括號讀起閱讀翰意。我試了一下,的確未定義的標(biāo)識符容易理解一些信柿。首先前三個就不說了冀偶,咱們直奔第四個。最后一個當(dāng)做一會閱讀完渔嚷,之后的一個練習(xí)进鸠,感興趣的朋友可以試試。
首先:一定得知道() / [] 的優(yōu)先級都大于*形病。
char (*(*x())[])();
step1: x() 右看
x是一個函數(shù)
step2: *x() 左看
x是一個函數(shù)客年,該函數(shù)返回一個指針
step3: (*x())[] 右看
x是一個函數(shù),該函數(shù)返回一個指針漠吻,這個指針指向一個數(shù)組
step4: *(*x())[] 左看
x是一個函數(shù)量瓜,該函數(shù)返回一個指針,這個指針指向一個數(shù)組途乃,該數(shù)組為指針數(shù)組
step5:(*(*x())[])() 右看
x是一個函數(shù)绍傲,該函數(shù)返回一個指針,這個指針指向一個數(shù)組耍共,該數(shù)組為指針數(shù)組烫饼,每個指針為
函數(shù)指針
step6:char (*(*x())[])() 左看
x是一個函數(shù),該函數(shù)返回一個指針划提,這個指針指向一個數(shù)組枫弟,該數(shù)組為指針數(shù)組,每個指針為
函數(shù)指針鹏往,函數(shù)返回char類型淡诗。
其實實際中很少使用到過于復(fù)雜的聲明,如果實在是用到復(fù)雜的聲明伊履,都會使用typedef進(jìn)行合成韩容。
char (*(*x())[])();
typedef *x() per1;
typedef *(per1)[] per2Arr;
char (per2Arr)();