C的語法在你第一次接觸時給你的感覺是靈活而松散,似乎隨便你怎么寫編譯器都能給予解釋——也就是可以順利的編譯通過,你甚至可以寫出 i = 96 +'a';之類的語句來。
但當你深入學習使用C的時候你會發(fā)現(xiàn)C的語法也有其詭譎的一面,其中聲明就是很討厭的一項。我記得自己在學習的時候是靠死記硬背一些基本的聲明方式來過關的,順便說說這種方法在很多情況下都是最好的方法之一。
我們首先來看C語言的術語以及一些能組合成一個聲明的單獨語法成分。其中一個非常重要的成分就是聲明器(declarator),它是所有聲明的核心。簡單來說,聲明器就是標識符以及與它組合在一起的任何指針,函數(shù)括號、數(shù)組下標等。下表是一個歸納分類
----------------------------------------------------------------------------------------------------------------------------------
數(shù)量 C語言中的名字 C語言中出現(xiàn)的形式
----------------------------------------------------------------------------------------------------------------------------------
零個或多個 指針 下列形式之一:
*const volatile
*volatile
*
*const
*volatile const
-----------------------------------------------------------------------------------------------------------------------------------
有且只有一個 直接聲明器 標識符
或:標識符[下標]
或:標識符(參數(shù))
或:(聲明器)
-----------------------------------------------------------------------------------------------------------------------------------
零個或一個 初始化內容 =初始值
-----------------------------------------------------------------------------------------------------------------------------------
一個聲明由下表所示的各個部分組成。聲明確定了變量的基本類型以及初始值(如果有的話)。
-----------------------------------------------------------------------------------------------------------------------------------
數(shù)量 C語言中的名字 C語言中出現(xiàn)的形式
-----------------------------------------------------------------------------------------------------------------------------------
至少一個類型說明符 類型說明符(type-specifier) void char short int long
signed unsigned
float double
結構說明符(struct-specifier)
枚舉說明符(enum-specifier)
聯(lián)合說明符(union-specifier)
存儲類型(storage-class) extern static register
auto typedef
類型限定符(type-qualifier) const volatile
-----------------------------------------------------------------------------------------------------------------------------------
有且只有一個 聲明器(declarator) 參見上表的定義
-----------------------------------------------------------------------------------------------------------------------------------
零個或多個 更多的聲明器 聲明器
-----------------------------------------------------------------------------------------------------------------------------------
一個 分號 ;
-----------------------------------------------------------------------------------------------------------------------------------
記住:在合法的聲明中存在限制條件。
1) 函數(shù)的返回值不能是一個函數(shù),象foo()()這樣是非法的
2) 函數(shù)的返回值不能是一個數(shù)組,象foo()[]這樣是非法的
3) 數(shù)組里面不能有函數(shù),象foo[]()這樣是非法的
優(yōu)先級規(guī)則:
1) 聲明從它的名字開始讀取,然后按照優(yōu)先級順序依次讀取
2) 優(yōu)先級從高到低依次是:
2.1) 聲明中被括號括起來的那部分
2.2)后綴操作符:()表示這是一個函數(shù),[ ]表示一個數(shù)組
2.3)前綴操作符: *表示“指向......的指針”
3) 如果const和(或)volatile關鍵字的后面緊跟類型說明符(如int long等),那么它作用于類型說明符。在其它情況下,const和(或)volatile關鍵字作用于它左邊緊鄰的指針星號。
<!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> <v:stroke joinstyle="miter" /> <v:formulas> <v:f eqn="if lineDrawn pixelLineWidth 0" /> <v:f eqn="sum @0 1 0" /> <v:f eqn="sum 0 0 @1" /> <v:f eqn="prod @2 1 2" /> <v:f eqn="prod @3 21600 pixelWidth" /> <v:f eqn="prod @3 21600 pixelHeight" /> <v:f eqn="sum @0 0 1" /> <v:f eqn="prod @6 1 2" /> <v:f eqn="prod @7 21600 pixelWidth" /> <v:f eqn="sum @8 21600 0" /> <v:f eqn="prod @7 21600 pixelHeight" /> <v:f eqn="sum @10 21600 0" /> </v:formulas> <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" /> <o:lock v:ext="edit" aspectratio="t" /> </v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" style='width:294.75pt; height:279pt'> <v:imagedata src="file:///C:/DOCUME~1/HZ07442/LOCALS~1/Temp/msohtml1/01/clip_image001.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]-->
<!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> <v:stroke joinstyle="miter" /> <v:formulas> <v:f eqn="if lineDrawn pixelLineWidth 0" /> <v:f eqn="sum @0 1 0" /> <v:f eqn="sum 0 0 @1" /> <v:f eqn="prod @2 1 2" /> <v:f eqn="prod @3 21600 pixelWidth" /> <v:f eqn="prod @3 21600 pixelHeight" /> <v:f eqn="sum @0 0 1" /> <v:f eqn="prod @6 1 2" /> <v:f eqn="prod @7 21600 pixelWidth" /> <v:f eqn="sum @8 21600 0" /> <v:f eqn="prod @7 21600 pixelHeight" /> <v:f eqn="sum @10 21600 0" /> </v:formulas> <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" /> <o:lock v:ext="edit" aspectratio="t" /> </v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" style='width:294.75pt; height:279pt'> <v:imagedata src="file:///C:/DOCUME~1/HZ07442/LOCALS~1/Temp/msohtml1/02/clip_image001.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]-->
<!--[endif]-->
例:
分析 char * const *(*next)();
這個東西表示“next是一個指針,它指向一個函數(shù),這個函數(shù)的返回一個char類型的常量指針”。
但當你深入學習使用C的時候你會發(fā)現(xiàn)C的語法也有其詭譎的一面,其中聲明就是很討厭的一項。我記得自己在學習的時候是靠死記硬背一些基本的聲明方式來過關的,順便說說這種方法在很多情況下都是最好的方法之一。
我們首先來看C語言的術語以及一些能組合成一個聲明的單獨語法成分。其中一個非常重要的成分就是聲明器(declarator),它是所有聲明的核心。簡單來說,聲明器就是標識符以及與它組合在一起的任何指針,函數(shù)括號、數(shù)組下標等。下表是一個歸納分類
----------------------------------------------------------------------------------------------------------------------------------
數(shù)量 C語言中的名字 C語言中出現(xiàn)的形式
----------------------------------------------------------------------------------------------------------------------------------
零個或多個 指針 下列形式之一:
*const volatile
*volatile
*
*const
*volatile const
-----------------------------------------------------------------------------------------------------------------------------------
有且只有一個 直接聲明器 標識符
或:標識符[下標]
或:標識符(參數(shù))
或:(聲明器)
-----------------------------------------------------------------------------------------------------------------------------------
零個或一個 初始化內容 =初始值
-----------------------------------------------------------------------------------------------------------------------------------
一個聲明由下表所示的各個部分組成。聲明確定了變量的基本類型以及初始值(如果有的話)。
-----------------------------------------------------------------------------------------------------------------------------------
數(shù)量 C語言中的名字 C語言中出現(xiàn)的形式
-----------------------------------------------------------------------------------------------------------------------------------
至少一個類型說明符 類型說明符(type-specifier) void char short int long
signed unsigned
float double
結構說明符(struct-specifier)
枚舉說明符(enum-specifier)
聯(lián)合說明符(union-specifier)
存儲類型(storage-class) extern static register
auto typedef
類型限定符(type-qualifier) const volatile
-----------------------------------------------------------------------------------------------------------------------------------
有且只有一個 聲明器(declarator) 參見上表的定義
-----------------------------------------------------------------------------------------------------------------------------------
零個或多個 更多的聲明器 聲明器
-----------------------------------------------------------------------------------------------------------------------------------
一個 分號 ;
-----------------------------------------------------------------------------------------------------------------------------------
記住:在合法的聲明中存在限制條件。
1) 函數(shù)的返回值不能是一個函數(shù),象foo()()這樣是非法的
2) 函數(shù)的返回值不能是一個數(shù)組,象foo()[]這樣是非法的
3) 數(shù)組里面不能有函數(shù),象foo[]()這樣是非法的
優(yōu)先級規(guī)則:
1) 聲明從它的名字開始讀取,然后按照優(yōu)先級順序依次讀取
2) 優(yōu)先級從高到低依次是:
2.1) 聲明中被括號括起來的那部分
2.2)后綴操作符:()表示這是一個函數(shù),[ ]表示一個數(shù)組
2.3)前綴操作符: *表示“指向......的指針”
3) 如果const和(或)volatile關鍵字的后面緊跟類型說明符(如int long等),那么它作用于類型說明符。在其它情況下,const和(或)volatile關鍵字作用于它左邊緊鄰的指針星號。
<!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> <v:stroke joinstyle="miter" /> <v:formulas> <v:f eqn="if lineDrawn pixelLineWidth 0" /> <v:f eqn="sum @0 1 0" /> <v:f eqn="sum 0 0 @1" /> <v:f eqn="prod @2 1 2" /> <v:f eqn="prod @3 21600 pixelWidth" /> <v:f eqn="prod @3 21600 pixelHeight" /> <v:f eqn="sum @0 0 1" /> <v:f eqn="prod @6 1 2" /> <v:f eqn="prod @7 21600 pixelWidth" /> <v:f eqn="sum @8 21600 0" /> <v:f eqn="prod @7 21600 pixelHeight" /> <v:f eqn="sum @10 21600 0" /> </v:formulas> <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" /> <o:lock v:ext="edit" aspectratio="t" /> </v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" style='width:294.75pt; height:279pt'> <v:imagedata src="file:///C:/DOCUME~1/HZ07442/LOCALS~1/Temp/msohtml1/02/clip_image001.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]-->
分析 char * const *(*next)();
這個東西表示“next是一個指針,它指向一個函數(shù),這個函數(shù)的返回一個char類型的常量指針”。
更多文章、技術交流、商務合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
