![](/img/trans.png)
[英]Can Clang warn me when I use non-standard functions provided by the GNU C Library?
[英]Can I get gcc/clang to warn me when an enum value isn't a key in an array?
我正在使用數組將枚舉與值相關聯:
parse_node_category parse_node_categories[] = {
[PT_ALL_EX_CALL] = PT_C_EXPRESSION,
[PT_ALL_EX_FN] = PT_C_EXPRESSION,
[PT_ALL_EX_FUN_BODY] = PT_C_EXPRESSION,
...
[PT_ALL_MULTI_DATA_CONSTRUCTORS] = PT_C_NONE,
[PT_ALL_MULTI_TYPE_CONSTRUCTOR_NAME] = PT_C_NONE,
[PT_ALL_MULTI_DATA_CONSTRUCTOR_NAME] = PT_C_NONE,
...
};
我希望編譯器檢查我的數組是否不再將每個鍵映射到一個值。 有沒有辦法做到這一點?
我知道我可以用一個開關來做到這一點,但我特別希望通過數組查找 map 鍵值。
如果我向我的枚舉添加一個新值,編譯器應該抱怨parse_node_categories
不包含與新枚舉值對應的值。
我們幾乎可以用幾乎正常的 C 做到這一點,也許我們能做的總比沒有好。
假設您有一個這樣的枚舉和數組:
enum {
epic_foo,
epic_bar
};
epic_value_t epic_mapping[] = {
[epic_foo] = grand_maneuver,
[epic_bar] = awesome_move
};
好吧,我們可以在枚舉中添加一個特殊的最后一個元素:
enum {
epic_foo,
epic_bar,
/* add enum members above this line */
epic_size
} epic_enum;
巧妙之處在於epic_size
現在是一個值為2
的常量表達式。
所以當你向枚舉添加另一個值時,如果你只是確保將它添加到大小占位符之前,
enum {
epic_foo,
epic_bar,
epic_qux,
/* add enum members above this line */
epic_size
} epic_enum;
epic_size
自動變為3
。
好的,現在我們能用它做什么?
好吧, sizeof(epic_mapping)
也是一個常量表達式。 該值是sizeof(epic_value_t)
的倍數,但我們可以執行正常的“獲取靜態定義數組中的元素數”技巧,這也是一個常量表達式: sizeof(epic_mapping)/sizeof(epic_mapping[0])
。
因此,讓我們快速將其保存在宏中:
#define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
現在,如果我們可以在編譯時檢查epic_size == ARRAY_SIZE(epic_mapping)
,我們就會有一個不錯的解決方案——它不會防止數組初始化中的漏洞,如果我們開始給枚舉成員,它也不會工作自定義值,但它至少會捕捉到將條目添加到枚舉末尾然后忘記將它們添加到數組的情況。
在現代 C 編譯器上,您可能有static_assert
,所以這只是添加的問題
static_assert(epic_size == ARRAY_SIZE(epic_mapping))
在數組定義之后。
如果你需要移植到舊的 C 編譯器,你可以濫用一些 C 規則來強制編譯錯誤,這取決於常量表達式的計算結果是真還是假(因為,例如,數組大小被允許是常量表達式並且永遠不會允許為負):
#if __STDC_VERSION__ >= 201112L
#include <assert.h> /* static_assert */
#else
#define static_assert(condition) sizeof(char[1 - 2*!!(condition)])
#endif
當枚舉值不是數組中的鍵時,我可以讓 gcc/clang 警告我嗎?
目前沒有這樣的功能。
您可以為 gcc 和 clang 編寫插件或創建補丁,並合並這樣的功能。
有沒有辦法做到這一點?
編寫您自己的 static 分析器來檢查它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.