如何理解c和c++的複雜類型聲明

首先,讓我們看看指針與const結合的聲明:
const int *p;//p是指向常量整型的指針
int const *p;//錯誤
int * const p;//p是指向整的常量指針
const int * const p;//p是指向常整形的常指針
怎麼樣?希望大家不會搞混吧,下面我會告訴大家如何去理解,但是寫到這裏,我突然想起const的一些東西,這裏先插個小插曲,-_-
相信大家在學習C++時也見到過用const修飾函數的,如:
const int fun();
int fun() const;
最後那個表示fun函數是常成員函數(c++類中),既fun函數不能修改類中的成員變量和成員函數,這個在大家學習MFC中會經常看到的,舉個例子:如HWND GetDlgItem(ID) const;這裏就不詳細說下去了,大家知道這麼個事就行了。

1、理論
一、我們先從編譯器中的聲明器(declarator)說起,什麼是聲明器?簡單來說,聲明器就是標識符和與它組合一起的任何指針、函數括號、數組下標等(定義請參考《c專家編程》),合法的聲明存在以下的限制:
1、函數的返回值不能是個函數或數組,所以fun()()和fun()[]是非法的
2、數組裏不能有函數,所以fun[]()是非法的

二、優先級規則
A、聲明從它的名字開始讀取,然後按照優先級從高到低讀取
B、優先級高低順序:
B1、聲明中被括號括起來部分
B2、後綴操作符:()表示函數  []表示數組
B3、前綴操作符:*表示指向...的指針
C、如果const和(或)volatile後面緊跟類型(如int等),則const和(或)volatile修飾類型,否則const和(或)volatile修飾緊跟在他們左邊的*指針。

2、練習

例子

根據上面的優先級規則,我們來進行下面的練習:
char * const * (*p)();
1、根據A規則,從p入手,得到p是...;
2、根據B1規則,(*p),得到p是指針,指向...;
3、根據B2規則,()函數下標優先於*,所以(*p)(),得到p是指針,指向一個函數,該函數返回...
4、根據C規則知道const是修飾它左邊的*不是右邊,所以右邊的*應該是函數的返回值,故得到p是指針,指向一個函數,該函數返回另外一個指針,該指針指向...
5、根據C規則知道指針指向一個類型爲char的常指針。
6、綜上述,得到p是指針,指向一個函數,該函數返回另外一個指針,而該指針指向一個類型爲char的常指針。

習題

以下給出些練習,鞏固下:
1、char * (*array[10]) (int **p)
2、void (*signal(int sig, void(*fun)(int)))(int)

相信大家對上面那些聲明也非常厭惡,那麼我們來找解決辦法吧,那就是使用typedef,比如對上面的練習中void (*signal(int sig, void(*fun)(int)))(int),用typedef來使用就是:

typedef void (*ptr_to_fun)(int)

ptr_to_fun signal(int, ptr_to_fun)
說到這,有些朋友會說:能不能用#define來解決呢??很好,是可以的啦,但是不好,爲什麼?很多朋友可能都知道了,因爲#define只是簡單的符號替換,不進行類型檢查,另外一些如#define max ((x)>(y)?(x)y))這些會帶來種種不好,這裏就不多說了,反正我除了爲常量使用#define外,我都不用#define。

3、答案
1、array是個數組,該數組的元素是指針,該指針指向一個函數,這個函數的參數是指向指針的指針p,函數返回另外一個指針,而這個指針又指向char類型。
2、fun是個函數指針,函數的參數是int,返回值是void,signal是個函數,其中一個參數是int,另外一個參數是fun,返回另一個指向函數的指針,該函數參數爲int,返回void(其實就是fun)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章