c++的基本復合型別主要有三種:陣列,引用和指標。
由於語法上的自由性,導致這三者巢狀的情況下變得十分複雜,雖然我們可以用更加簡便,易於閱讀的方案替換一些複雜宣告,但是我們還是有必要掌握複雜程式的閱讀能力。
舉個栗子:
int* ( *(
*func )( int* ) )[10];
是不是覺得很無厘頭,放心,今天我們就來細細說說如何理解和使用復合型別的混合使用。
這裡是一位大神的理解:
原文如下:
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.直譯如下:
右左法則是這樣的:從最裡面的括號開始閱讀,然後從右向左讀。當遇到括號時,我們就掉轉閱讀方向,一旦括號裡的所有東西解析完畢,跳出括號。一直這樣重複直到表示式解析完畢。我們可以這樣理解:
所謂的最裡面的括號,指的是包含變數名的最小括號。
然後我們要記住四種運算子的優先順序:
這樣我們就基本掌握了閱讀順序,可惜,僅僅是掌握閱讀順序是不夠的,筆者這裡有一種思路,我們暫且叫它替換規則,有助於我們理解巢狀表示式。
我們在理解了閱讀順序之後,從最裡面的括號開始,按照運算子優先順序,逐步替換複雜表示式為單一表示式,最終轉化為單一復合型別的形式。
注意,我們使用變數名來替換內層表示式時最好符合一定規則,具體見例子。
筆者的描述可能有一定偏差,我們直接來看例子,先從簡單的開始:
例項1
int *(&array)[10] = ptrs;
我們按照之前的規則,逐步地來:
int *ref[10] = ptrs;
int
*ref_arr = ptrs;
ref_arr_ptr_int我們按照從左向右解析這個變數名:
array是乙個引用,引用的物件是陣列,陣列的元素是指標,指標指向的物件為int例項2也就是存放十個int指標的陣列的引用(好拗口)
我們繼續複雜點的例子:
int(*func)(int *p, int(*f)(int*));
int ptr(int *p, int(*f)(int*));
int prt_fun(int *p, int(*f)(int*));
int prt_fun(ptr_int, ptr_fun(ptr_int));
解析如下:
func是乙個函式指標,返回值為int,該型別函式的引數為兩個,乙個是int指標,另乙個是乙個函式指標,引數為int指標(:)更加拗口了)例項3
這下我們再來看文章開頭的例子
int* ( *( *func )( int* ) )[10];
int* ( *ptr( int* ) )[10];
int* ( *ptr_fun( ptr_int ) )[10];
int* ( ptr_fun_ptr )[10];
這裡我們怎麼理解呢,這裡特別地,函式的下乙個物件我們理解為函式的返回值,這裡說明返回值是乙個指標
int* ptr_fun_ptr_arr;
重頭戲,來理解這個表示式:
func是乙個函式指標,函式的引數是int指標,返回值是乙個指標,指標指向陣列,陣列內部存了10個int指標規則總結
這裡補充總結一點解析規則:
1、按照從左往右的順序解析
2、遇到fun表明是函式,如果fun後面不是(),則表明後面是返回值,省略了引數列表,引數和返回值都需要隔斷開單獨理解。
有了這兩個規則,基本上能理解所有的表示式了。
使用舉例–函式返回二維陣列
我們知道,由於陣列是不可拷貝的,所以返回值不允許是陣列,但是我們可以返回其首位址指標來得到二維陣列
這裡是乙個很好的例子(不是筆者寫的,筆者能理解,但是並不會寫這樣奇怪複雜的函式)
當然,如果你熟練掌握了c++的記憶體結構,也可以強制的通過指標操作得到二維陣列的所有元素
int ( *fun( int( & )[3][3] ) )[3];
......
int main( void )
int ( *fun( int( &a )[3][3] ) )[3]
雖然有所謂的規則便於閱讀理解複雜表示式,但是我們在實際使用當中傾向於使用更加方便的**風格,例如使用typedef
例項3可以這樣表達:
typedef
int*(*ret)[5];
typedef ret(*func)(int *);
其實typedef就是一種編譯器層面的替換規則。
在物件導向的程式中,使用函式指標需要使用functional標頭檔案的方法,關於std::bind和std::function,本篇不做多介紹,記住在類中不能簡單地使用函式指標,我們有機會再詳細地介紹這一塊的內容。
型別的右左法則
讀作 指向.的指標 讀作 的陣列 讀作 返回.的函式 找到宣告中的識別符號 identifier 它就是你分析的起始點,讀作 identifier 是.看你的識別符號右邊 a 如果發現 你將知道這是乙個函式宣告,這時你可以說 identifier 是返回.的函式 b 如果發現 你將知道這是乙個陣列宣...
指標的右左法則
指標的右左法 右左法則 右左法則的英文原文翻譯 首先從最裡面的圓括號開始閱讀,然後向右看,再往左看。每當遇到圓括號時,就應該調轉閱讀方向。一旦解析完圓括號裡面所有東西,就跳出圓括號。重複整個過程直到整個宣告解析完成。其實左右法則就是以標示符為中心點,自右向左旋轉解讀指標的宣告含義。例如 int a ...
C語言複雜定義的讀法(右左法則)
右左法則的運用 右左法則 先找到變數,先向右邊看再向左邊看,看到括號代表函式,方括號代表陣列,代表指標。int arr 5 arr是乙個函式指標陣列,該陣列裡的元素指向乙個形參為空,返回值為函式指標,該指標指向乙個形參為空,返回值為int fioat b b是函式,該函式形參為空,返回值為陣列指標,...