2016-02-03 77 views
1

從維基百科的文章enumerated types引述將是這個問題最好的開口道:枚舉計算機內存

換句話說,枚舉類型有彼此不同的值,並且可以進行比較並且被分配,但是未被指定爲,程序員在計算機的存儲器中具有任何具體的表示;編譯器和解釋器可以任意表示它們。

雖然我理解的定義和枚舉的用途,我還不能掌握枚舉和內存之間的互動 - 當一個枚舉類型聲明創建枚舉類型變量的情況下,是類型定義作爲聯盟或結構存儲在內存中?上述維基摘錄背後的含義是什麼?

+1

我對枚舉的看法是,它們只在編譯時間之前存在(在c中,無論如何)。即它們在編譯時被替換爲它們的整數值 –

+0

在不同的編程語言中,表示和實現可能是非常不同的。當你問C時,請閱讀關於C'enum's。 – Olaf

+0

它基本上是說如果你有一個枚舉變量,編譯器可以選擇任何適合其需要的內存基本類型。給定'enum Xyz {ABC,DEF,GHI};',C程序員(實際上是程序員)無法控制用於存儲'enum Xyz'值的內存類型。在C語言中,它可以是'char'或'short'或'int'或編譯器的其他類型 - 除非有一個ABI(應用程序二進制接口)定義編譯器必須執行的操作。 –

回答

1

維基百科摘要並未專門討論C的enum類型。 C標準對於enum的工作方式有一些特定的要求。

枚舉類型與char或某些帶符號或無符號整數類型兼容。表示的選擇取決於編譯器,編譯器必須記錄它的選擇(它是實現定義的),但類型必須能夠表示枚舉的所有值。

枚舉常量的值在0默認情況下,並且將每一個連續的恆開始由1

enum foo { 
    zero, // equal to 0 
    one, // equal to 1 
    two // equal to 2 
}; 

的常量是int類型始終,無論什麼樣的enum類型本身就是兼容。 (常數是枚舉類型更有意義;由於歷史原因,它們的類型爲int。)

您可以指定部分或全部常量的值 - 這意味着該值不一定是截然不同的:

enum bar { 
    two = 2, 
    deux = 2, 
    zwei = 2, 
    one = 1, 
    dos // implicitly equal to 2 
}; 

定義枚舉類型不會導致任何存儲在內存中運行。如果你定義了一個枚舉類型的對象,該對象的值將被存儲在內存中(除非它被優化掉),並且將佔用sizeof (enum whatever)字節。這與任何其他類型的對象相同。

枚舉常量被視爲常量表達式。表達式two幾乎與常數2相同。

請注意,C++對於enum類型有一些不同的規則。你的問題被標記爲C,所以我不會詳細討論。

+0

很好的答案 - 謝謝!然而,我在兩個地方感到困惑。首先,你提到枚舉類型由編譯器表示爲'char','uint'或者其他,取決於編譯器的設置。有沒有可能的'字符'值比無符號整數,所以如果默認'枚舉'對象'uint'或編譯器自動執行'chars'填滿是不是更實際?其次,如果枚舉常量是「枚舉」類型的,那麼這是否意味着這些常量中的每一個都將具有一系列可以使用的值?只是一個較小的範圍? – agromov

+1

@Agrus:我不確定'uint'是什麼意思;沒有這樣的標準類型。一個'enum'類型可以具有與'char'相同的表示形式,任何有符號整數類型或者任何無符號整數類型。編譯器可以以任何喜歡的方式進行選擇。至於枚舉常量,常量有一個單一的固定值,而不是一個值的範圍。 –

+0

也許'uint'對於嵌入式系統編程更爲常見。然而,你說得對,'uint'不是一個標準類型,也許它被用於簡單的目的。如果一個'enum'沒有賦值,那麼編譯器會自己決定分配給它的類型,不管是char或int,對吧?如果程序員沒有指定值,那麼他們從0開始。那麼如果定義的枚舉常量的數量大於可用的「字符數」,會發生什麼?這完全是假設,因爲它看起來像枚舉相當短。 – agromov

1

這意味着枚舉常量不需要位於內存中。你不能把他們的地址。

這允許編譯器將所有對枚舉常量的引用替換爲它們的實際值。例如,代碼:

enum { x = 123; } 
int y = x; 

可編譯就好像它是:

int y = 123; 

如果枚舉類型而不創建枚舉類型變量的實例聲明,是存儲在所述類型定義記憶是一種聯盟還是一種結構?

在C中,類型主要是編譯時構造;一旦程序被編譯成機器碼,所有的類型信息就消失*。訪問一個結構成員是「通過這個指針訪問n個字節的內存」。

因此,如果編譯器內嵌所有枚舉,如上所示,那麼枚舉在編譯代碼中根本不存在。

*除了可選的調試信息部分,但通常只能由調試器讀取。

+0

謝謝你的迴應!這是否意味着如果在代碼中將'x'聲明爲'y'之前的變量,那麼將'y'賦值爲'x'(即y = x),則會得到'x'的地址被放置在存儲器中,並在達到該指令時複製該地址處的任何內容? – agromov