程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Chapter_03 分析C語言的聲明

Chapter_03 分析C語言的聲明

編輯:關於C語言

  • 3.1 只有編譯器才會喜歡的語法

C語言的聲明語法(聲明模型)很晦澀,容易成為程序員的障礙,正是由於在組合類型方面的笨拙行為,C語言顯得很復雜。

造成這種情況的原因是因為“類型模型(type model)”這個概念對於當時的編程語言理論而言尚屬陌生。BCPL(C語言前身)語言幾乎沒有類型,其以二進制字作為唯一的數據類型。 C語言的設計哲學之一:對象的聲明形式與它的使用形式要盡可能相似。 int *p[3]是一個int類型的指針數組。 其使用方法如下:
    
     * p[
     a0[] = {, ,  a1[] = {,  a2[] = {-, , , , 
    p[] =] =] =( i = ; i < ; i++, p[]++ , *p[( i = ; i < ; i++, p[]++ , *p[( i = ; i < ; i++, p[]++ , *p[
其執行結果如下:     C語言的聲明所存在的最大問題是你無法以一種習慣性的從左向右的方式閱讀一個聲明。   關於const 指針所指向的對象是只讀的兩種聲明:
      i [] = {, 
      * grape ;     
      * orange ;    
    grape = &= & , *grape );  
    grape++;                    
    printf(  , *grape );  

 

指針本身是只讀的聲明:
     i = 
     *  apple = &*apple += ;   
, *apple );  

指針本身是只讀
且指針所指向的對象也是只讀的兩種聲明:
      i = 
      *  grape_jam_1 = &  *  grape_jam_2 = &+= ;   
    *grape_jam_1 += ;  
上面這段代碼所產生的錯誤如下:   總結的規則:在指針的聲明中,只要const“緊挨著”指針變量就說明該指針本身是只讀的,否則就是該指針所指向的對象是只讀的。  
  • 3.2 聲明是如何形成的
聲明器(declarator)是所有聲明的核心。 聲明器:標識符以及與它組合在一起的任何指針(*)、函數括號(())、數組下標([])等。   關於結構(struct)   結構就是一種把一些數據項組合在一起的數據結構。其語法為:
 { 內容 ... };
結構的定義後可以跟一些變量名,表示這些變量的類型是這個結構:
 { 內容 ... } plum, pomegranate, pear ;
struct關鍵字後可以加一個可選的“結構標簽”,可以作為結構的簡寫形式(structfruit_tag)用於以後定義變量:
 fruit_tag { 內容... } plum, pomegranate , pear;
因此,結構的通常形式:



作者建議不要把結構的聲明和變量的定義混合在一起,而是分開,使代碼更容易閱讀。
變量的聲明應該與類型的聲明分開。
 
兩個跟結構有關的參數傳遞問題:
第二點如下代碼所示:


 a[];   


 s_tag twofold( ( j = ; j < ; j++*= ( i = ; i < ; i++= == lemon;      
}
結構中包含一個指向結構本身的指針,這種方法常用於列表(list)、樹(tree)等。   關於聯合(union)   結構中每個成員依次存儲,而在聯合中,所有成員都成偏移量為0處開始存儲,在某一時刻,只有一個成員真正存儲於該地址。聯合因此也叫“變體記錄”。 聯合的一般形式:



聯合一般作為大型結構的一部分存在。用以節省存儲空間,因為某些數據項不可能同時出現。
聯合也可以把同一個數據解釋成兩種不同的東西,而不是把兩個不同的數據解釋為同一種東西。
作者最後列舉數據(15W行與機器無關的OS源代碼),說明結構出現的次數大約是聯合的一百倍。
 
關於枚舉(enum)
 
枚舉通過一種簡單的途徑,把一串名字與一串整型值聯系在一起。
對於C來說,很少有什麼事只能考枚舉來完成而無法用#define解決的。
枚舉的一版形式:





缺省情況下,整型值從0開始。如果對列表中的某個標識符進行了賦值,那麼後面的標識符依次大1。
枚舉與#define的一個不同:#define定義的名字一般在編譯時被丟棄,而枚舉名字通常在調試器中一直可見。
 

  • 3.3 優先級規則
要理解一個聲明,必須要懂得其中的優先級規則。 理解C語言聲明的優先級規則: A    聲明從它的名字開始讀取,然後按照優先級依次讀取。 B    優先級順序:     B.  1    聲明中被括號括起來的部分     B.  2    後綴操作符:                   ()  表示這是一個函數                []  表示這是一個數組     B.  3    前綴操作符: * 表示“指向...的指針”。 C     如果const、volatile關鍵字的後面緊跟類型說明符(int long float),那麼它作用於類型說明符。在其他情況下,其作用於它緊鄰的指針星號。  
  • 3.5 關於typedef
在某些方面,typedef類似於宏文本替換——它沒有引入新類型,而是為現有類型取個新名字。 一般情況下,typedef用於簡潔地表示指向其他東西的指針。 不要在一個typedef中放入幾個聲明器;不要把typedef嵌入到聲明的中間部分。 在同一個代碼塊中,typedef引入的名字不能與其他標識符同名。  
  • 3.6  typedef和define的區別
typedef和宏文本替換之間存在的兩個方面的區別: 1. 可以用其他類型說明符對宏類型名進行擴展,但對typedef定義的類型名就不能這樣做;
   peach   int
2. 在連續幾個變量的聲明語句中,用typedef定義的類型能夠保證聲明中所有的變量均為同一種類型,而#define定義的類型則無法保證。
 d_string char* *

 

  • 3.7  C語言中的名字空間
C語言中的名字空間: 在同一個名字空間裡,任何名字都必須具有唯一性,但在不同的名字空間裡可以存在相同的名字。
typedef 

 fruit mandarin;  
如上這種情況,結構標簽與typedef的結構別名具有了相同的名字,作者在此處建議:當你有兩個不同的東西時,一個比較好的原則就是用不同的名字來稱呼它們。這樣做減少了混淆的危險(這始終是軟件的一個重要准則)。比如此處可以在結構標簽後加一個"_tag"後綴。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved