c語言中的複雜原型聲明是很多人都頭痛的事,下面我說一下自己的理解。主要是從理解的角度說明聲明的內容。
1.首先是從左往右找到未聲明的標識符,
2.再找將未宣告身份識別符括起來的最裡層的小括弧的一大塊,再根據運算子的等級(提醒越是裡面的小括弧優先順序比外面的小括弧就有優先,如(*(*func)(int *))將*func括起來的比將*(*func)(int *)括起來的優先)和結合性來分析,當分析時遇到指標時的下一步就應該確定指標指向什麼類型 /遇到數組時下一步就確定數組的元素內容是什麼個數是多少 /遇到函數時的下一步就確定函數的類型(函數的類型即函數參數是什麼返回又是什麼)
3.每分析完一層小括弧就往外跳到又是將未宣告身份識別符括起來的一大塊,再根據第2步,如此迴圈直至將整塊聲明都分析完
下面開始來例子(聲明例子來源於網上的,大家可以在網上找一些關於例子中聲明的分析)
執行個體1如下: int (*func)(int); (網上的分析) 先看標識符,(*func)是一個整體標識符 再看右邊,有(),故這個標識符是表示一個函數,其有一個int型的參數 最後看左邊,有個int,表示這個函數是返回整形 再回溯,(*func)是一個函數,那麼func自然是一個指向函數的指標 綜上,func是一個函數指標,該函數有一個整形參數,並返回整形值 上例出自C吧的貼子http://tieba.baidu.com/f?kz=925000075 int (*func)(int); (根據整理的方法分析) 首先從左往右找到未聲明的標識符(這裡是func).再找將標識符括起來的所有小括弧中最裡層的那個小括弧,最裡層的小括弧括起來的一大塊是(*func),修飾標識符func的是*,所以func是一個指標,現在就開始確定指標指向什麼類型,這裡因括弧裡的內容分析完了就跳出來找第二個將它包起來的小括弧(由裡往外數最裡層的小括弧為一),往外數這裡沒有第二個將標識符括起來的小括弧,而只剩int ( ) (int);。再根據優先順序來看 int ( ) (int) 中(int)比 int 要高。 所以指標func是一個指向函數的指標(此時要確定函數類型即參數和傳回值各是什麼) (int)裡面是函數的參數即為int, 在int ( ) (int)左邊的int 是函數的傳回值 則 func是一個指標(指向什麼),該指標指向一個函數(函數是什麼類型即參數和傳回值各是什麼)。該函數指標指向的函數類型是帶一個int型參數,返回一個int。 或直接說 func是一個指向一個類型(這類型是指指標指向函數的類型)為帶int整形參數返回一個int的函數指標 |
|
|
執行個體2如下: int (*func[5])(int *p); (網上的分析) func右邊是一個[]運算子,說明func是一個具有5個元素的數組,func的左邊有一個*,說明func的元素是指標,要注意這裡的*不是修飾func的,而是修飾func[5]的,原因是[]運算子優先順序比*高,func先跟[]結合,因此*修飾的是func[5]。跳出這個括弧,看右邊,也是一對圓括弧,說明func數組的元素是函數類型的指標,它所指向的函數具有int*類型的形參,傳回值類型為int int (*func[5])(int *p); (根據整理的方法分析) 首先找未聲明的標識符再找將該標識符括起來的最裡層的小括弧,即是 (*func[5])根據優先順序知func是一個數組(數組元素的內容是什麼),此時括弧裡還有*沒分析。所以*修飾func[ ],即數組元素的內容是指標(指標指向什麼),跳出括弧再根據優先順序得 ( ) 比 int 高,即指標指向函數(函數的參數和傳回值是什麼),函數的類型帶一個(int *p)參數傳回值一個 int。 綜合可得: func是一個元素個數為5數組(數組元素的內容是什麼),數組元素的內容是一個指標(指向什麼),該指標指向一個函數(參數和傳回值各是什麼),函數指標指向的函數類型是帶一個(int *p)參數,返回一個int. 或說: func是一個元素個數為5的指標數組,該指標數組的內容指向一個類型是帶一個(int *p)參數返回一個int的函數指標 再下面的說法不知行不行? func是一個元素內容為指向類型是帶一個(int *p)參數返回一個int的函數指標數組,該函數指標數組大小為5 |
|
|
8樓 執行個體3如下: int *func(int *)[5]; (根據整理方法的分析) 首先找到未宣告身份識別符,這裡是func,再找小括弧(這裡沒將它括起來的小括弧),根據等級知 ( ) 比 * 高,func是一個函數,函數帶一個(int *)參數,返回什麼? 有根據等級知 [ ] 比 * 高,即函數返回一個元素個數為5的數組,數組的元素內容是什麼,*修飾數組的內容是指標,int表該指標指向一個int。 綜合來說: func是一個函數,函數帶一個(int *)形參,返回一個數組元素個數為5的數組,數組元素的內容是指標,該指標指向的類型是int。 或說: func是一個帶(int *)參數返回一個元素個數為5的指標數組的函數, 指標數組的內容是(int*)。 但函數返回一個元素個數為5的數組正確嗎? NO 則該聲明int *func(int *)[5]不符合規則 若用小括弧將*func(int *)括起來呢? 即int ( *func(int *) )[5],請自己動手試試分析該聲明以及判斷正確與否 請根據方法自行分析以下聲明以及判斷正確與否 int *func[5](int*); |
|
|
執行個體4如下: int (*(*func)[5])(int *p); (網上的分析) func被一個圓括弧包含,左邊又有一個*,那麼func是一個指標,跳出括弧,右邊是一個[]運算子號,說明func是一個指向數組的指標,現在往左看,左邊有一個*號,說明這個數組的元素是指標,再跳出括弧,右邊又有一個括弧,說明這個數組的元素是指向函數的指標。總結一下,就是:func是一個指向數組的指標,這個數組的元素是函數指標,這些指標指向具有int*形參,傳回值為int類型的函數。 int (*(*func)[5])(int *p); (根據整理的方法分析) 首先找未聲明的標識符再找將該標識符括起來的最裡層的小括弧,即(*func)可知func是一個指標(指向什麼),跳出括弧即到(*( )[5]),根據優先順序知 [ ] 比 * 高;所以指標func指向一個元素個數為5的數組(數組元素的內容是什麼),(括弧裡還有*即)*是修飾數組的元素內容是指標(指標指向什麼),再跳出括弧即為int (*( )[ ])(int *p),優先順序中( ) 比 * 高,所以指標指向函數(函數的參數和返回是什麼),指標指向函數的類型是帶一個(int *p)參數返回一個int。 則綜合分析: func是一個指標,該指標指向元素個數為5的數組,數組元素的內容是指標,該指標指向類型是一個帶(int *p)參數返回一個int的函數指標。 或說: func是一個指向元素個數為5的數組指標,該數組元素的內容是一個指向類型為帶一個(int *p)參數返回一個int的函數指標 |
|
|
執行個體7如下: int (*(*(*func)(int *))[5])(int *); (網上的分析) func是一個函數指標,這類函數的傳回值是一個指向數組的指標,所指向數組的元素也是函數指標,指向的函數具有int*形參,傳回值為int。 (根據整理的方法分析) (分析提醒:將未聲明的標識符func括起來的小括弧有三個(在這例裡將*func括起來的小括弧(紅色)是第一個/最裡層,將*(*func)(int *)括起來的小括弧(藍色)是第二個,將*(*(*func)(int *))[5]括起來的小括弧(綠色)是第三個/最外層,最裡的( )優先順序會先屏蔽相對於它來說屬外的( ) ,即在分析時應該是紅色的小括弧/(最裡的小括弧)會屏蔽藍色的小括弧/(由裡往外數是第二個小括弧),分析到藍色的小括弧時,藍色的小括弧會綠色的小括弧/(由裡往外數是第三個小括弧) ,以此類推 ………… 綜合來說就是越是裡面的小括弧優先順序比外面的小括弧就有優先順序)) int (*(*(*func)(int *))[5])(int *); 首先找到將未聲明的標識符擴起來的最裡層小括弧,這裡是(*func),所以func是一個指標,括弧裡的全部都分析完了就跳出括弧,即到(*( )(int *)),因( )比*高所以指標func指向函數,指標指向的類型是一個函數,該函數的參數是(int *),*修飾帶一個(int*)形參函數的傳回值是指標,第二個括弧裡的全部也都分析完了就跳出括弧即( * ( ( )( )) [5] ) 因 [ ] 比 * 高,所以函數返回的指標指向元素個數為5的數組,此時括弧裡的*修飾的是數組元素的內容為指標,第三個括弧裡的全部也都分析完了就跳出括弧 即int ( ( ( ) ( ) ) [ ] ) (int *)又根據優先順序知數組元素內容是一個指向函數的指標,該函數類型帶一個(int *)參數,返回一個int數。 則 int (*(*(*func)(int *))[5])(int *); func是一個指標,指標指向的類型是帶一個(int *)參數返回一個指標,該指標指向元素個數為5的指標數組,該指標數組的元素內容是一個指向類型為帶一個(int *)參數返回一個int的函數指標。 或: func是一個指向類型為帶一個(int *)參數返回一個指向個數為5的指標數組的函數指標,該指標數組的元素內容指向一個類型為帶(int *)返回int的函數指標 |
|
|
以下兩例子請自己分析,總結的答案在下面給出(建議讀者學完後到網上找一些更為複雜的例子來鞏固對複雜聲明的分析和理解) void (*signal(int signum,void(* handler)(int)))(int); (上面的聲明是signal.h下signal的聲明) int (*(*func[7][8][9])(int*))[5]; …… …… …… …… …… …… …… …… void ( *signal ( int signum,void(* handler)(int) ) ) (int); signal是一個帶( int signum, void(* handler)(int) )參數返回一個指向類型為帶一個(int)參數無返回的函數指標,signal帶的第一個參數是int,第二個參數是指向類型帶一個int參數無返回的函數指標。 int (*(*func[7][8][9])(int*))[5]; func是一個7*8*9(三維)指標數組,7*8*9(三維)指標數組的元素內容是一個指向類型為一個帶(int*)參數返回一個指向元素個數為5且指向類型為int的數組指標的函數指標 int (*(*func[7][8][9])(int*))[5]; func是一個指向類型是帶一個(int*)返回一個指向元素個數為5且類型是int的數組指標的函數指標數組,該函數指標數組大小為7*8*9. |