2011-10-25 54 views
7

編譯器,C或C++(例如gcc)如何承認const聲明?「const」是如何實現的?

例如,在以下代碼中,編譯器如何保持跟蹤變量ciconst並且無法修改?

int 
get_foo() { 
    return 42; 
} 

void 
test() 
{ 
    int i = get_foo(); 
    i += 5; 

    const int ci = get_foo(); 
    // ci += 7; // compile error: assignment of read-only variable ?ci? 
} 
+5

跟蹤所有關於var的編譯時信息的相同方式iables? –

+0

它通過類型系統在編譯時完成。 –

+1

您的評論應爲「賦值爲只讀變量」。順便說一句,你如何看待編譯器知道它的整數? – hplbsh

回答

9

很像變量(地址,類型等)的任何其他位符號信息。通常有一個符號表存儲有關已聲明標識符的信息,每當遇到另一個標識符引用時,都會查詢它。大多數語言在編譯後都會丟棄符號表,因此即使標識符被聲明,您也可以操作編譯後的代碼並強制一個新的值'const'需要一個複雜的運行時系統(和代碼簽名)來防止這種情況。)

+0

爲了補充說明,一個標準問題C++/C編譯器在運行時並沒有做太多的事情來保持像這樣的「const」這樣的變量,它只知道不生成任何可以通過符號表修改這個值的代碼Kilian提到。因此,一些其他編譯器可能會創建一些代碼,如果該代碼被加載到進程中,它可能會覆蓋該位置的內存。那很糟。 – Dlongnecker

+1

Const數據可以放在不同的內存塊中,在某些系統上,內存塊實際上會被標記爲只讀。就像代碼本身駐留在不同的段中一樣(也許const數據和代碼可能會混合在一起)。當然,這隻適用於靜態常量,沒有任何東西在堆棧上創建。 –

1

編譯器知道ciconst因爲你行

const int ci = get_foo(); 

。當你穿過ci各地的其他功能或將其分配給其他變量告訴它,編譯器保留該const-通過阻止你做任何可能改變其價值的事情。

例如,以下產生編譯器錯誤。

int *ci2 = &ci; 
(*ci2)++; 

因爲編譯器不會讓你修改ci的值。

+0

即使沒有增量操作,後面的示例也會產生編譯器錯誤。我們不能將一個指向const的值賦給一個指向非const的變量。 – Novelocrat

3

當然它是由每個編譯器的實現,但概括地說,它與其它信息一起存儲所述變量的constvolatile限定符(如果有的話)在其可變符號表如變量的類型,以及是否它是一個指針/參考。

+0

「CV限定詞」?當然,變量沒有簡歷! – Gabe

+1

@Gabe:標準在第3.9.3節「CV限定符」中談論了很多關於它們(const/volatile)的內容。 –

1

我確信其他人可以詳細說明,但總之,是的。編譯器跟蹤所有類型說明符,以便它知道ci的類型是「const int」,而不是「int」。

1

正如其他人所說的那樣,const由編譯器跟蹤,編譯器跟蹤變量爲int這一事實。事實上,我已經讀過,至少gcc認爲const int是與int不同的類型,所以它甚至不被跟蹤爲修飾符,它的跟蹤方式與int完全相同。

需要注意的是,你實際上可以通過指針鑄造改變const的價值,但結果是不確定的:

#include <stdio.h> 
#include <stdlib.h> 

int main(void) { 
     const int c = 0; 
     printf("%d\n", c); 
     ++*(int*)&c; 
     printf("%d\n", c); 
} 

在使用gcc我的機器,這個打印

0 
1 

但隨着編譯g ++給出

0 
0