2011-09-15 63 views
7

下面的文本是從C Programming Language, 2nd Edition的摘錄,由C語言的創造者寫的(所以我相信這是正確的):爲什麼不是由C編譯器檢查的枚舉?

雖然枚舉類型的變量可以聲明,編譯器不需要檢查你在這個變量中存儲的是枚舉的有效值。

我有些疑惑:

  1. 對於何種情況下,在C語言中沒有編譯器檢查的enum的價值?
  2. enum由於某種原因,不會檢查常量。爲什麼不?原因是什麼?
  3. 由於enum未被編譯器檢查,是否使用enum容易出錯?請解釋。
+0

近距離投票爲什麼? –

+1

有人認爲這是/ questions/432937/net-why-arent-enums-range-value-checked的副本。他們可能改變了主意(答案是一樣的,但問題畢竟是一種不同的語言),但不可能取消近距離投票。 –

回答

8
  1. 枚舉就像是一個奇特的整數,它比定義常量或預處理器宏作爲要存儲的常數值名稱的整個負載更好,因爲編譯器(或編輯)檢查您是否使用了正確的名稱和數值以符合正確的類型。另一方面,只是一個整數,沒有什麼能阻止你輸入一個你沒有給出名字的值,這個值偶爾是有用的。

  2. 它們不能在任何情況下檢查。如果將兩個數字加起來得到要放入枚舉類型變量中的值,會怎麼樣?它可以是任何在運行時生成的值,所以它不能被檢查(至少沒有很多開銷)。

  3. C中的一切都是不安全的;幾乎沒有編譯器可以完全阻止您濫用的功能。枚舉是安全的,因爲它們有效地防止程序員錯誤和混淆,而不是因爲它們阻止你做一些愚蠢的事情。

+0

enum's的另一個好處是有些編譯器會警告你,如果你有一個'switch'塊來打開一個'enum',並且你從'case'子句中留下一個。 – detly

+0

我認爲這對某些編譯器來說是一件煩人的事情,而不是關於'enum'的一件好事。由於早先的邏輯排除了其他值,所以某個'switch'只處理可能的'enum'值的一個子集是很有可能的,甚至可能...... –

+0

@R ..:在那個* ahem *的情況下,你可以只需添加'default:/ *錯誤handlign代碼* /'來消除警告。 –

6

你可以這樣做

enum status { 
    ST_READY = 1 << 0, /* 1 */ 
    ST_WAIT = 1 << 1, /* 2 */ 
    ST_ERROR = 1 << 2, /* 4 */ 
    ST_HALT = 1 << 3, /* 8 */ 
    ST_ETC = 1 << 4, /* 16 */ 
}; 

一個枚舉然後定義該類型

enum status status; 

的對象,並將其設置爲一些「簡單」的位或狀態

status = ST_WAIT | ST_ERROR; /* recoverable error */ 

請注意,值ST_WAIT | ST_ERROR6,並且該值不是枚舉的一部分。


回答您的問題:

  1. C編譯器讓程序員拍攝自己的腳。
  2. C編譯器讓程序員在腳下自拍。
  3. C編譯器讓程序員在腳下自拍。
+0

+1 C只是假設你知道你在做什麼,並讓你以儘可能高效的方式繼續下去 - 也是:g/foot/s //頭/ – asc99c

+1

@ asc99c:我會這樣做: %s/foot/head/g' – pmg

+0

@pmg你能說'1 << 0'這個結果是什麼值? –

1

1)在什麼情況下,所有的C語言做的編譯器不檢查值像枚舉關注。

我不能不明白說出你的部落。

1)在C語言的所有情況下,編譯器都不檢查枚舉的值。 [編輯]

當你分配給它。允許從裸整數分配,因此您可以這樣做:

enum E { A, B } x; 
x = 10000; 

沒有編譯器錯誤。此外,枚舉中的switch不能檢查詳盡性。

2)爲什麼枚舉常量沒有被檢查,出於某些原因?這些原因是什麼?

人們喜歡把整數放入其中。例如。

enum E { END_OF_EVERYTHING = 5 }; 

其中0-4是指普通值,5是特殊類型。

3)由於枚舉不是由編譯器檢查,使用枚舉容易出錯?

是的。由於枚舉只可以採取一切枚舉值的比特數最少的值,就可以得到奇怪的結果:

enum E { A = 1, B = -1 }; 

這個枚舉只包含2位數據(值-2,-1,0,1 )。如果你將10000分配給它,奇怪的事情可能會發生(實際上看到)。

+0

在此代碼中enum E {A = 1,B = -1};',你怎麼能說這些值是-2,-1,0 ,1? –