[英]Dead branch of _Generic expression causing compiler error (C11)
我很想寫一個類型驗證宏,它只在類型不是int / short / long或pointer時才發出警告。
我遇到的麻煩是指針可以是任何類型的指針。
#define INT_OR_POINTER_AS_UINTPTR(v) _Generic((v), \
signed long: (uintptr_t)(v), unsigned long: (uintptr_t)(v), \
signed int: (uintptr_t)(v), unsigned int: (uintptr_t)(v), \
signed short: (uintptr_t)(v), unsigned short: (uintptr_t)(v), \
default: (((void)(0 ? (*(v)) : 0), (uintptr_t)(v))))
第一個塊是允許int/short/long
default
情況是允許任何指針。
(0 ? (*(v)) : 0)
的意圖是,如果v
不是指針,則導致編譯器錯誤,但否則不影響所生成的代碼(將0 ? ...
改為)。
這樣,來自其他類型(例如float
或bool
意外隱式轉換將不會被忽略。
理想情況下,這將起作用。
int a = 4;
struct Foo *b = NULL;
uintptr_t test_a = INT_OR_POINTER_AS_UINTPTR(a);
uintptr_t test_b = INT_OR_POINTER_AS_UINTPTR(b);
理想情況下,這兩種用途都會失敗。
float a = 4;
struct Foo b = {0};
uintptr_t test_a = INT_OR_POINTER_AS_UINTPTR(a);
uintptr_t test_b = INT_OR_POINTER_AS_UINTPTR(b);
但是,即使以int/long/short
作為參數,也會評估檢查指針的代碼並出錯: invalid type argument of unary '*' (have 'int')
不必顯式枚舉可能傳遞給此_Generic
每種類型的指針,是否有一種方法可以捕獲所有類型的指針,而無需為其他(非指針)值評估表達式?
_Bool
是“標准無符號整數類型”,請參見6.2.5,因此,如果要對此進行特殊處理,則需要單獨進行處理。
否則,您可以使用一個簡單的技巧。 整數和指針的性質是對稱差是整數。 因此,我們在只能接受整數的上下文中使用對稱差,例如數組下標:
#define INT_OR_POINTER_AS_UINTPTR(v) \
((sizeof "Allow only integer and pointer types"[(v)-(v)]), (uintptr_t)(v))
對於struct
類型,該減法將失敗,並且浮點類型將產生一個浮點差,該差不能用於指針算術。
要拒絕_Bool
,可以使用_Generic
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.