C陷阱篇之enum預設長度
enum型用於定義常量集合,相比#define有一些優勢,如:enum是一種資料型別,使用時會檢查型別匹配;enum增加了範圍約束,避免變數賦值和使用時超出定義範圍。但enum也有一個隱含問題:enum變數佔用的空間與編譯器相關。
多數編譯器預設enum型長度等於int型,很多人也把enum型變數等同於int,但C標準在這裡留下了尾巴:“列舉型尺寸是能夠容納最大列舉子值的整數尺寸”,“列舉型別中列舉子的值必須要能用一個int型表述”。也就是說,列舉型的尺寸不能超過int型,但不必等於int型,只要能容納最大列舉子就行,下例:
enum EType1 { e1 = CHAR_MAX };
enum EType2 { e2 = SHORT_MAX };
這兩個列舉型別最小可用char、short的記憶體空間表示,即有可能:
sizeof( EType1 ) == sizeof( char );
sizeof( EType2 ) == sizeof( short );
一些編譯器為節約記憶體可以設定這種“量體裁衣”的策略。如ADS就有圖示選項(enum container always int),選定後enum變數長度為int,否則就等於能容納最大列舉子的最短長度。gcc也有類似選項-fshort-enums,預設不設定,一旦設定就選用節省記憶體的enum長度。
enum長度不確定會帶來可移植性問題,如果第三方庫API介面使用enum型別,編譯和呼叫庫時一旦有關enum長度的編譯器設定不一致,API介面層對數值的解析就不匹配。比如上層應用編譯時沒有用-fshort-enums,預設用4位元組空間來儲存使用enum變數,而編譯庫時設定了fshort-enums,則庫內部此enum size可能為1。當把enum變數地址傳進API時,內部只修改變數最低位元組,高3位元組值無變化(內容隨機),API返回時,上層使用的4位元組enum變數值就可能隨機。(潛規則篇之API介面)
因此內部程式碼使用enum型別優於define,但對外API介面儘量避免用enum型。
在用keil做關於STM32的專案時,就碰到這樣的的問題,可以通過設定列舉變數為固定int型別來保證與上位機的一致。
轉自:ipmux https://blog.csdn.net/ipmux/article/details/17334099