C語言中有時會出現復雜的聲明,比如
char * const * (*next) (); //這是個什麼東東?
在講復雜聲明的分析方法前,先來個補充點。
C語言變量的聲明始終貫徹兩點:
1.聲明和使用的語法盡量保持一致
例如:
#include <iostream> using namespace std; double (*fun)(double); //聲明一個函數指針 int main(){ fun=sin; doube reslut=(*fun)(0.5);//使用這個函數指針 ... }
2.聲明語句不是的閱讀不是按照從左往右的閱讀順序,而是要根據各個符號的優先級進行閱讀的
這點非常重要!先列出C語言聲明的優先級規則,再舉個例子就能掌握求解方法了。
C語言聲明的優先級規則
A 聲明從它的名字開始讀取,然後按照優先級順序依次讀取;
B 優先級從高到低依次是:
B.1 聲明中被括號括起來的那部分;
B.2 後綴操作符:
括號()表示這是一個函數,而
放括號[]表示這是一個數組;
B.3 前綴操作符:星號*表示這是一個“指向...的指針”;
C 如果const和(或)volatile關鍵字的後面緊跟類型說明符(如int,long等),那麼它作用於類型說明符。在其他情況下,它作用於關鍵字左邊緊鄰的指針星號。
需要強調的一個重要注意點是,對於優先級: () > [] > * 。
舉例,用優先級規則分析C語言聲明一例:
char * const * (*next) ();
按照規則解讀 char * const * (*next) ();
首先,(*next) 表示next是一個指針,它指向某個東東;
根據B.2和最右邊的括號,next指向一個函數;
根據B.3,第二個星號表示,該函數返回一個指針;
char * const是函數返回的指針所指向的類型;
char* 是字符指針,const修飾左邊的星號,即字符指針是常量的,該指針不可修改(該指針指向的字符內容是可修改的);
綜合地表述為,next是一個指針,它指向一個函數,該函數返回一個指針,該指針指向一個類型為char的常量指針。
還是不明白?再往下看就明白了!
#---------------------------------------------------------------------------------#
總結一下,分析復雜的C語言聲明,要采用"由內而外,層層剝離”的策略。
從哪裡開始剝?從語句的最左邊的標志符開始剝(上例為從next開始)。
往哪個方向剝?依照C語言的優先級規則一層層剝。
#---------------------------------------------------------------------------------#
再舉一例作詳細說明:
char *(* c[10]) (int **p);
第一步,char *(* c[10]) (int **p); 最左邊的標志符是c,表示"c是一個什麼東東";
第二步,char *(* [10]) (int **p); 和[10]結合,表示"c是一個長度為10的數組";
第三步,char *(* ) (int **p); 和*結合,表示"這個數組存放著指針";
第四步,char * (int **p); 和(int **p)結合,表示"這個指針指向一個函數,函數的參數是二維指針";
第五步,char * ; 和 * 結合,表示"這個函數返回一個指針";
第六步,char ; 這個指針指向一個字符;
把上面六步串起來,讀作: c是一個數組[0..9],它存放著指針,指針指向的函數參數是一個二維指針返回值是指向字符的指針。完工!
#---------------------------------------------------------------------------------#
注1: 這個方法若理解了,什麼指針數組和數組指針、指針函數和函數指針等等之類的區別都是小菜一碟了。
注2: 合法的聲明中存在限制條件。如函數的返回值不能是一個函數,也不能是一個數組,所以像function()()和function()[]是非法的,不能出現。數組裡面能存函數指針,但不能存函數,像int (* function[])()是合法的,function[]()則是非法的。
#---------------------------------------------------------------------------------#