C語言 複雜型別宣告

2021-09-07 01:30:44 字數 4053 閱讀 5114

c語言所有複雜的指標宣告,都是由各種宣告巢狀構成的。如何解讀複雜指標宣告呢?右左法則是乙個既著名又常用的方法。不過,右左法則其實並不是c標準裡面的內容,它是從c標準的宣告規定中歸納出來的方法。c標準的宣告規則,是用來解決如何建立宣告的,而右左法則是用來解決如何辯識乙個宣告的,兩者可以說是相反的。右左法則的英文原文是這樣說的:

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.

這段英文的翻譯如下:

筆者要對這個法則進行乙個小小的修正,應該是從未定義的識別符號開始閱讀,而不是從括號讀起,之所以是未定義的識別符號,是因為乙個宣告裡面可能有多個識別符號,但未定義的識別符號只會有乙個。

現在通過一些例子來討論右左法則的應用,先從最簡單的開始,逐步加深:

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言語的複雜型別宣告 

在c言語的複雜型別宣告中,我們用到3個修飾符:*、()、。含義如下: 

* 暗示宣告乙個指標 

() 暗示宣告乙個函式 

暗示宣告乙個陣列 

c語言允許我們一次使用多個上面所說明的修飾符來申明乙個變數,這樣我們可以構造出多種多樣的類別來。 

大家先看下面的例子: 

int board[8][8]; //二維陣列(乙個8個元素的陣列,元素內容還是陣列) 

int **p; //指向指標的指標(乙個指標,內容還是乙個指標) 

int *array[10]; //10個元素的陣列,元素內容是指標。 

int (*p)[10]; //乙個指標,指向含有10個元素的陣列。 

int *oof[3][4]; //3個元素的陣列,存放的內容是指標,指標分別指向4個元素的陣列 

int (*oof)[3][4]; //乙個指標指向3*4 的陣列。 

看到這裡,可能有人會想,你在說些什麼哦,怎麼看不明白,沒有關係,看完下面的3條法則,你在來看上面的內容就很清晰了。 

1:離名字越近的修飾符優先順序越高 

2:,()優先順序比*高 

3:用()括起來的表示式的優先順序最高。 

從裡面摘抄點東西過來。關於const 挺有用的。

我先總結一下:

下面是原文:

繼續補充:加上const。以上對於複雜宣告的理解,明眼人一看就知道僅僅是從右值的角度入手。要理解const,就必須不可不提到左值了。左值右值是c++中的基本概念,三言兩語也說不清楚。最粗淺的看法,左值指可以被寫入,也就是說能出現於賦值語句的左邊;右值指可讀,只能在賦值表示式的右邊。當然,一般來說,左值往往可以當做右值來使用,可寫往往意味著可讀。而const的作用,就是將原本可寫的東西,給整成唯讀的了。具體到表示式來說,就是某些表示式的值具備左右值,而const就是去掉了它的左值功能。舉例說吧,還是從最簡單說起。

int a; 表示式a的結果是int型,既是左值又是右值;

const int 

a;,a返回的結果是int型別,但是此結果已不再可寫了,也即是a不能放在賦值語句的左邊了。

int const a; 可這樣理解,先不理int 

const,a是乙個變數,既可讀又可寫,const將a整成唯讀。int表示const a的結果型別。雖然,理解上這樣,但對編譯器來說,const int 

a;和int const a;都一樣,都只是表達了同樣的意思,a是乙個整型常量。

const int 

*p;,*p結果為int型,加上const後,*p只能讀了,所以,p是整形指標,其所指的內容只能讀不能寫,但p本身卻可寫。 int const 

*p;,則先強調*p的唯讀性,然後再說明*p為int型。其實,這兩種寫法的意思都一樣。

int *const p;,const 緊挨著p,說明p本身唯讀。至於 int 

*,則表示*p型別為int,可讀寫。因此,p是整形指標,p本身不可寫,但其所指的內容卻可讀又可寫。說實在,不明白這樣的指標變數有什麼鬼用,實際的**應該用的很少才是。

為了表達指標的唯讀純潔性的概念,不僅指標本身不能寫,連其指向的內容也不可修改,c++終於整出了下面這樣偉大的**。int 

const *const p;或者const int * const 

p;。c++的這種做法,俗稱致力於解決臆想中的問題,因為const與指標的組合,實際上只有指標所指向的內容只能讀很有意義,其他的,意義微乎其微。

C語言的一些複雜型別宣告

一些比較複雜的宣告例項 c primer plus中的例子 陣列後面的和函式名後面的 具有相同的優先順序,它們比 的優先順序高。都是從左往右結合。int board 8 8 int ptr 乙個指向指標的指標,每個元素都是乙個指向int的指標 int risk 10 內含10個元素的陣列,每個元素都...

如何理解c和c 的複雜型別宣告

首先,讓我們看看指標與const結合的宣告 const int p p是指向常整形的指標 int const p 錯誤 int const p p是指向整形的常指標 const int const p p是指向常整形的常指標 怎麼樣?希望大家不會搞混吧,下面我會告訴大家如何去理解,但是寫到這裡,我突...

如何理解c和c 的複雜型別宣告

本文作者girlrong是網易廣州社群的c語言版 版主,這篇 文章被選在 精華區。很是不錯,不敢獨享!據說她樂於助人,虛心誠懇,頗受歡迎。只可惜現在已退隱江湖了。在最近學習c語言過程中,了解些前輩大牛的經驗看法 曾經碰到過讓你迷惑不解 類似於int fp1 int 10 這樣的變數宣告嗎?對上述 右...