C:運算式、語句、聲明

來源:互聯網
上載者:User

  有網友在http://www.cnblogs.com/pmer/archive/2013/03/15/2960809.html 129樓問

  “運算式、語句、聲明之間的區別到底是什嗎?”

  這個問題對很多人來說確實很模糊,甚至很多出版物中也有很多錯誤的講述,故此本文力圖對此做一詳盡說明和澄清。

運算式(Expression)

     根據C標準,運算式(Expression)是運算子(operator)和運算元(operand)所構成的序列,例如"3+2"。最簡單的情形,也可能沒有運算子,例如“3”。

     可能需要特意提一下的是,函數調用也是運算式。例如 sqrt(1.0),這裡的“()”是一個運算子,sqrt和1.0則是“()”這個運算子的運算元。

     運算式所表達的可能是要求電腦進行值的計算(computation of a value),例如“3+2”這個運算式,表示的就是要求電腦求3+2的值。當然,運算式同時也表示這個計算所得到的值。 

     運算式還可能用來指明一個資料對象(object)或一個函數(function)。例如,若有 int i; 那麼在 i = 1 這個運算式中的 i 這個子運算式就是指 i 所代表的那個object——一塊連續的記憶體。再比如, 運算式 & printf 中,printf這個子運算式表示的是相應的printf()庫函數。

     除此之外,運算式可能產生副效應(side effects),例如printf("ABC") 這個運算式的值是3,其副效應是在標準輸出裝置上連續輸出A、B、C這三個字元。再比如,對於 int i; 運算式 i = 3 的值是3,副效應是 i 所代表的資料對象被寫入了3。

語句(Statement)

    C語言語句(Statement)的定義從其功能上來說有些含糊:語句規定的是一種“動作”(action)。這種動作最顯著的特點是規定了如何跳轉或結束。例如,對於int i; "i = 1 ;"這條語句的意義是到“;”位置時 i = 1 這個運算式求值(Evaluate), 即值的計算和副效應必須完成。再比如“return ;”語句規定的是跳轉到另一位置繼續執行。

     儘管語句的功能有些含糊,但其文法形式確實極其清晰的。形式上較為簡單的語句有:

     運算式語句(expression-statement),形式為:

     expression ;

     其中的運算式是可選的。這種語句以“;”作為結束標誌。對於初學者來說最常見的運算式語句是調用printf()函數所形成的:printf("Hello World\n");

     跳躍陳述式(jump-statement),包括:

     goto 語句、continue 語句、break 語句和return 語句。這種語句也以“;”作為結束標誌。         

     複合陳述式(compound-statement),其一般形式為:

     {block-item-list}

     其中的block-item-list可以有也可以沒有,可以是聲明,也可以是語句。

     有一點特別需要說明,複合陳述式並非以“;”作為結束標誌。這表明語句中不一定有“;”。國內C語言書中有一種常見的陳詞濫調:“一個語句必須在最後有一個分號,分號是語句中不可缺少的組成部分”(譚浩強,《C程式設計》第四版,p58),那絕對在是瞪著眼睛說胡話。因為複合陳述式的最後就不需要有分號。最簡單的複合陳述式只有一對“{}”,根本就沒分號什麼事兒。

     其他的語句都是構造性的,即是在其他語句的基礎上構造出來的。比如標號語句(labeled-statement),就是在語句前加一冒號及其他內容:

     identifier : statement

     case constant-expression : statement

     default : statement

     選擇語句也是依據類似的原則在語句的基礎上構造的:

     if ( expression ) statement
     if ( expression ) statement else statement
     switch ( expression ) statement

     值得一提的是switch語句並不一定是在複合陳述式的基礎上構造的,這和很多人的常識不同。例如,

     switch ( i ) case 0:case 1:case 2:printf("ABC\n");

     就是一條完全合法的switch語句。  其功能等價於

     if (i==0||i==1||i==2)  printf("ABC\n");

     C語言的迴圈語句同樣是在語句的基礎上構造而成。

      while ( expression ) statement
  do statement while ( expression ) ;
      for ( expressionopt ; expression ; expression ) statement
      for ( declaration expression; expression ) statement

      在這些語句中,只有do-while語句最後一定是以“;”作為結束標誌。

      總之,由於複合陳述式並不是以分號作為結束標誌,而很多語句都是在語句的基礎上進一步構造而成,因此除了運算式語句、跳躍陳述式及do-while語句一定是以分號結束,其他語句則可能以分號結束,也可能不以分號結束,分號並不是語句必須的組成部分。

聲明(Declarations)

  除了static_assert declaration(C11),聲明的作用都是向編譯器解釋一個或多個標識符的含義及屬性。

      C標準給出的聲明的一般形式為

      declaration-specifiers init-declarator-list ;

      因此,通常情況下聲明都有“;”。

      但實際上,函數定義同時也是聲明(A definition of an identifier is a declaration),在格式上卻與此不符。

      儘管功能明確,形式簡單,但聲明其實是C語言中最複雜的成分,至少是之一。這種複雜性被 declarator 漠然地掩蓋起來了。 

      C語言要求每個聲明至少要聲明一個 declarator 、一個tag或一個枚舉成員。也就是說

      int i ;//沒問題,i是declarator

      int ; //違法,無declarator

      struct t;//合法,聲明了一個tag——t

      enum { A };//是合法的,聲明了枚舉成員A

      struct { int a ;}; //違背語言要求,可能招致警告。(在C語言早期,並不違反標準)

      union { int a ;};  //違背語言要求,可能招致警告。(在C語言早期,並不違反標準) 

      聲明不是語句(《C Primer Plus》一書把聲明稱為“聲明語句”,明顯是把C++的概念張冠李戴到C上面了)。一個簡單的證明是,聲明無法按照語句規則構成語句。譬如

      if( 1 ) int i ; //這在C語言中是不成立的

      有些聲明也叫定義(definition),所有的定義都是聲明。包括

      導致保留儲存區的對象聲明。最典型的就是局部變數的聲明。

      含有函數體的函式宣告,即函數定義。函數定義儘管在形式上不符合由“;”結尾的形式,但同樣是一個聲明,有時也被稱之為外部聲明(external declaration)或外部定義(external definition)。但習慣上,很多人所說的“函式宣告”往往特指那些非定義式的函式宣告。

      除此之外,枚舉常量(enumeration constant)和typedef name也是定義。

      declaration-specifiers包括儲存類別說明符(storage class specifier),類型說明符(type specifier) ,類型限定符(type qualifier),函數說明符(function specifier),從C11起又增加了一個對齊說明符(alignment specifier)。

      和多數人常識不符的是,typedef也屬於儲存類別說明符(storage class specifier)。

      把typedef類型定義歸為聲明並把typedef關鍵字作為儲存類別說明符(storage class specifier)只是為了文法描述上的方便。實際上typedef並沒有像其他幾個儲存類別說明符(extern,static,auto,register,_Thread_local(C11))那樣對儲存類別做出任何說明。

      在每個聲明中,儲存類別說明符只能出現一次。C11引人新的儲存類別說明符_Thread_local之後,這個說法不再成立了。

      類型說明符(type specifier)包括:void、char、short、int、long、float、double、signed、unsigned、_Bool、_Complex、atomic-type-specifier、struct-or-union-specifier、enum-specifier、typedef-name,使用時可能是類型說明符的某種組合,譬如 long double。其中_Bool、_Complex是C99新增的,最初還增加了一個_Imaginary,後來又刪除了。atomic-type-specifier是C11新增的。此外,C11在struct-or-union聲明中正式支援了匿名結構體或聯合體(anonymous structures and unions)。

      類型限定符(type qualifier)在C90中只有const和volatile兩個,const借鑒的是C++,volatile則完全是C標準委員會的發明。C99增加了一個restrict,只用於指標類型,提出這個限定符的目的是更好地最佳化。C又增加了一個_Atomic類型限定符。這個限定符也是唯一的一個Atomic type specifiers,這種Atomic 類型說明符是C11新增的內容。

      函數說明符(function specifier)是C99之後出現的。C99增加了一個inline這個函數說明符,C11又新增了一個_Noreturn函數說明符用來說明不返回調用者的函數,例如exit()函數。

     C11增加的另一個新的聲明說明符是對齊說明符(alignment specifier)。對齊問題不再像以前那樣猶抱琵琶半遮面,而是直接擺到了案頭上。

     聲明的init-declarator-list部分由一個或多個用“,”分隔的init-declarator組成。init-declarator可以是一個單獨的declarator或初始化形式declarator = initializer。

     最簡單的declarator是一個標識符。這是一種direct-declarator。在direct-declarator前面可以加* type-qualifier-list用以聲明指標。聲明指標時type-qualifier置於*的右側。而在declaration-specifiers中則沒有這樣的次序要求。

     direct-declarator還可以具有下面幾種形式:

     ( declarator )
     direct-declarator [ type-qualifier-list assignment-expressionopt ]
     direct-declarator [ static type-qualifier-list assignment-expression ]
     direct-declarator [ type-qualifier-list static assignment-expression ]
     direct-declarator [ type-qualifier-list * ]
     direct-declarator ( parameter-type-list )
     direct-declarator ( identifier-list )

     第一種中的“()”可能改變對declarator的類型解釋(例如:int *p[1];int (*p)[1];)。     

     自C99起,不再要求聲明數組時[]內是整數常量運算式,可以用變數描述數組尺寸。例如 int a[n]; 這就是所謂的VLA。VLA是C99的正式特性,在C11中則是一個可選特性。編譯器可以支援,也可以不支援。至於[]內的* 、static及type-qualifier-list,只用於聲明函數參數時。

     函式宣告“()”內雖然可以有parameter-type-list和 identifier-list兩種形式,但後者其實是一種正在逐步廢棄的形式,即

     void f(a)

     int a;

     {/*……*/}
    這種形式。除了在老代碼中可以看到,現在已經很少有人這樣寫了。現代風格的C語言提倡函數原型風格的聲明,即 參數為parameter-type-list這種形式。這種形式有兩種:

     parameter-list

     或
     parameter-list , ...

     “...”用於聲明參數個數不定的函數。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.