理解C語言函式宣告 複雜指標解析之右左法則

2021-10-11 08:36:09 字數 2625 閱讀 4188

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.

右左法則:首先從最裡面的圓括號看起,然後往右看,再往左看。每當遇到圓括號時,就應該掉轉閱讀方向。一旦解析完圓括號裡面所有的東西,就跳出圓括號。重複這個過程直到整個宣告解析完畢。

筆者要對這個法則進行乙個小小的修正,應該是從未定義的識別符號開始閱讀,而不是從括號讀起,之所以是未定義的識別符號,是因為乙個宣告裡面可能有多個識別符號,但未定義的識別符號只會有乙個。當然,這裡的未定義識別符號,是去除引數列表裡的形參識別符號。例如:void (*signal(int signo, void (*func)(int)))(int); 其中signo與func就是要忽略的未定義識別符號,void (*signal(int , void (*)(int)))(int)。這樣,只剩下signal為未定義識別符號。

int (*func)(int *p);

首先找到那個未定義的識別符號,就是func,它的外面有一對圓括號,而且左邊是乙個*號,這說明func是乙個指標,然後跳出這個圓括號,先看右邊,也是乙個圓括號,這說明(*func)是乙個函式,而func是乙個指向這類函式的指標,就是乙個函式指標,這類函式具有int*型別的形參,返回值型別是int。

int (*func)(int *p, int (*f)(int*));

func被一對括號包含,且左邊有乙個*號,說明func是乙個指標,跳出括號,右邊也有個括號,那麼func是乙個指向函式的指標,這類函式具有int*和int (*)(int*)這樣的形參,返回值為int型別。再來看一看func的形參int (*f)(int*),類似前面的解釋,f也是乙個函式指標,指向的函式具有int*型別的形參,返回值為int。

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被乙個圓括號包含,左邊又有乙個*,那麼func是乙個指標,跳出括號,右邊是乙個運算符號,說明func是乙個指向陣列的指標,現在往左看,左邊有乙個*號,說明這個陣列的元素是指標,再跳出括號,右邊又有乙個括號,說明這個陣列的元素是指向函式的指標。總結一下,就是:func是乙個指向陣列的指標,這個陣列的元素是函式指標,這些指標指向具有int*形參,返回值為int型別的函式。

int (*(*func)(int *p))[5];

func是乙個函式指標,這類函式具有int*型別的形參,返回值是指向陣列的指標,所指向的陣列的元素是具有5個int元素的陣列。要注意有些複雜指標宣告是非法的,例如:

int func(void) [5];

func是乙個返回值為具有5個int元素的陣列的函式。但c語言的函式返回值不能為陣列,這是因為如果允許函式返回值為陣列,那麼接收這個陣列的內容的東西,也必須是乙個陣列,但c語言的陣列名是乙個右值,它不能作為左值來接收另乙個陣列,因此函式返回值不能為陣列。

int func[5](void);

func是乙個具有5個元素的陣列,這個陣列的元素都是函式。這也是非法的,因為陣列的元素除了型別必須一樣外,每個元素所占用的記憶體空間也必須相同,顯然函式是無法達到這個要求的,即使函式的型別一樣,但函式所占用的空間通常是不相同的。

int(*

(*func)[5

][6]

)[7]

[8];

int(*(

*(*func)

(int*)

)[5]

)(int*);

int(*(

*func[7]

[8][

9])(

int*))

[5];

實際當中,需要宣告乙個複雜指標時,如果把整個宣告寫成上面所示的形式,對程式可讀性是一大損害。應該用typedef來對宣告逐層分解,增強可讀性,例如對於宣告:

int (*(*func)(int *p))[5];

可以這樣分解:

typedef

int(

*para)[5

];typedef para (

*func)

(int*)

;

參考

C語言複雜的宣告(陣列指標和函式指標)

int a 8 8 乙個內含int陣列的陣列 int ptr 指向指標的指標,被指向的指標指向int int b 10 指標陣列,內含10個元素的陣列,每個元素都是指向int型別的指標 int b 10 陣列指標,乙個指向陣列的指標,該陣列有10個int型別的值 int c 3 4 二維指標陣列,每...

C語言複雜指標理解

學習和使用c語言近十年了但對c語言的複雜指標依然有些迷糊索性花點時間分析一下,下面是一些心得,希望對讀者有所幫助 取the c programming language中的兩個例子以分析 char x char x 3 5 若直接讓我們說出這兩個x分別是什麼意思往往會有一些困難,這裡我們可以使用代入...

理解複雜C宣告

在看別人程式火寫程式之肯定會先宣告變數那如何正確的去看這些宣告,首先需要知道 右左法則 這在理解複雜宣告時很重要。在使用 右左法則 時先確定變數的位置。先向變數的右邊讀再向左邊讀。先從簡單開始 int a 整型變數 int a 整型指標變數 int a 整型指標的指標變數 int a 10 整形指標...