C語言基本知識之------聲明與定義

來源:互聯網
上載者:User
聲明與定義

    以前學C語言的時候,你有木有為下面的類似聲明而迷惑呢:

const int *p;

int const *p;

int * const p;

    這裡的const到底是修飾int,還是int*呢? 對於這幾個聲明的理解,是一些公司偏重的面試題。曾經我也很努力地去記住每一個聲明的具體意義,但是過了沒多久就又全忘了。最近看了《C專家編程》一書中的解釋,才晃然間感覺到是真的有些懂了。

 

那麼什麼是聲明,什麼是定義呢?

    首先我們先想一下,什麼是聲明,什麼是定義,為什麼會有這兩個東西在C語言中出現?

    我個人覺得,在現實世界中,我們可以把聲明理解為一種告示。聲明就是告訴別人說,這裡有這麼一個東西是屬於誰的或者是什麼樣的一件事情等等。當然這個告示你可以貼的到處都是,以防有的人會看不到。因此,聲明可以有多份。

    類似地,在C語言的世界裡,聲明一個變數,就是通告說在某個地方有這麼一個變數存在,我們瞭解了地方有之後,就可以拿來使用了。

    定義說白了就是為某個東西取一個統一的意思,它也是一種特殊的聲明。在C語言裡,定義就是一種特殊的聲明,定義一個變數的時候編譯器會為其分配記憶體。

    因此,在C語言中同一變數可以被聲明多次,但只能被定義一次(因為定義的時候分配記憶體,記憶體只分配一次就夠了)。

 

怎麼解析變數的聲明?

    既然有了聲明,那麼想一下,聲明在編譯器中又是怎樣被解析的呢?我們寫的任何程式都是用來執行的,要執行程式,編譯器肯定就要先理解程式。只要我們知道電腦是怎麼來理解這些語言的,我們也就能很輕易的理解這些相關的知識了。

    像上面提到的三個聲明:

const int *p;

int const *p;

int * const p;

    編譯器會怎樣理解呢?它會怎麼定位這三個p的具體意義呢?當然,編譯器是木有思想的,它只會一步步的去執行,所以編譯器的開發人員肯定會為它制定一個規則,告訴它說怎樣怎樣去一步步的理解程式中的聲明。並且,這個規則必須是無二義性的,要不然編譯器就會迷茫而不知道應該去選擇那個意思去理解了。

    想一想,如沒有一個指定的規則,而讓編譯器隨便去解析就好的話,那麼我們的同一段程式就有可能會有很多不同的結果。這樣一來,電腦的世界其不是亂了套了。

    因此,只要我們抓著編譯器的理解規則,就能輕而易舉地現理解聲明的具體意義了。

 

關於C的聲明,編譯器的解析規則是這樣的:

[

編譯器,從最左邊開始讀取,碰到第一個標識符就認定這是我們要定義的變數,接著它就按照如下的優先順序依次讀取並解析聲明:

p1, 如果當前讀到的標識符被括弧括了起來,它就先解析括起來的那部分

p2, 解析完括弧裡的內容,它會向後看一眼,看看後面有什麼東西不。

      如果後面碰到[],就解析為數組;如果後面碰到()就解析為函數

p3,看完後面,就向前看一眼,如果前面有*就說明是指標。

另外,編譯器規定,const/volatile 一般修飾其後面緊跟的類型說明符,否則它作用於其左邊的符號。

]

 

舉幾個例子,來模仿下編譯器的解析過程:

例1, char * const * (* next) ();

1, char * const * (* next) (); 第一步,編譯器讀取到左邊的第一個標識符next, 表示定義一變數next

2, char * const * (*        ) (); 第二步,解析標識符被括起來的部分:同樣按照優先順序規則,先看一下next後面,木有東西;然後看一下next的前面,有一個*。說明 next是個指標。

3,char * const *             (); 第三步,看完括弧中的部分,看一下後面,有()說明,next指向的是一個函數。

4,char * const *               ; 第四步,看完後面,看一下前面*,說明函數的傳回值是一個指標。

5,char * const                  ; 第五步,解析const, 按照規定,const修飾它後面緊跟的類型說明符,此處const後面沒有類型說明符。所以它修飾其左邊的 *, 說明是常指標

6, char *                            ; 第六步,char *,說明是指向字元的指標。

總結以上的解析過程可得,next是一個指標,它指向函數,函數的傳回值是一指標,指向一個常指標,常指標指向的內容是字元。簡言之,next是一個指向函數的指標,函數返回指向字元常指標的指標。

 

例2,文章剛開始處提到的三個聲明

按照編譯器規定,

const int * p; 因為const 後面緊挨著int, 所以它修飾int,說明是常整型。這裡p是指向const int的指標;

int const * p; 因為const 後面緊跟的不是類型說明符,所以它作用於其左邊的int,因此這裡的解析為p是指向const int的指標;

int * const p; 因為const 後面緊跟的不是類型說明符,所以它作用於其左邊的int *,因此這裡的解析為p是const 指標,它指向int類型的變數。

 

總結

    知道了編譯器的解析規則,以後碰到各種聲明我們都可以自己按照編譯器的思路去解析了,而不用再死記硬背每一個聲明具體代表什麼意思。因此,知其然並知其所以然才是王道。

    本人在這裡自己寫出來,主要是為了鞏固自己的知識理解。如果有人對這塊知識點感興趣 建議大家還是去看看《C專家編程》的第三章分析C語言的聲明或研究下C語言聲明解析的原始碼。相信在哪裡你會得到更好的解釋,通過別人轉達過來的知識,終歸會有些變味地。

 

參考文獻:

1,《C專家編程》------第三章 分析C語言的聲明

2,推薦一個關於C聲明的解析網站:www.cdecl.org

從這個網站上我們還可以下載c語言聲明的解析代碼,有興趣的可以研究下。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.