[英]How to create a macro to detect the type and print a number automatically?
我有一個宏:
#define assert_equal(x, y) do {\
typeof(x) evalx = x;\
typeof(y) evaly = y;\
_assert(evalx == evaly, __LINE__, __FILE__,\
EVAL_TYPE_FORMATER(evalx)" != "EVAL_TYPE_FORMATER(evaly), evalx, evaly\
)\
} while (0)
它應該測試 x 和 y 是否相等,如果不相等則打印兩個值。 _assert()
function 看起來像這樣:
void _assert(bool condition, size_t line, const char* file, char* format, ...);
我需要幫助來創建宏EVAL_TYPE_FORMATER()
。 我最初的想法是檢查#if
和typeof()
我必須使用什么格式字符串。 但這不起作用,因為我不能在宏擴展中使用#if
。
這是我的初步想法:
#define EVAL_TYPE_FORMATER(exp)\
#if typeof(exp) == char ||\
typeof(exp) == short ||\
typeof(exp) == int\
"%d"\
#elif typeof(exp) == long\
"%ld"\
...
但是正如您所看到的,is 有很多錯誤。 我該怎么做才能解決這個問題?
編輯:
較新的方法是使用_Generic
(感謝@Someprogrammerdude)。
#define EVAL_TYPE_FORMATER(exp) (_Generic((exp), \
char: "%d", \
short: "%d", \
int: "%d", \
long: "%ld", \
...
))
但是_Generic
的結果不能用於將它與常量連接起來。 EVAL_TYPE_FORMATER(evalx)" != "EVAL_TYPE_FORMATER(evaly)
現在無法編譯。 有辦法解決嗎?
編輯 2:
通過將_assert()
更改為現在采用 3 char*
arguments 並在運行時連接格式字符串來解決。
使用您當前的設計:
通過將 _assert() 更改為現在采用 3 char* arguments 並在運行時連接格式字符串來解決。
如果您打算使用 printf,這正是您必須要做的。
有辦法解決嗎?
當然:創建所有類型的所有可能組合並在一個表達式中計算它們:
#define assert_equal(x, y) do {\
typeof(x) evalx = x;\
typeof(y) evaly = y;\
_assert(evalx == evaly, __LINE__, __FILE__,\
EVAL_TYPE_FORMATER(evalx, evaly), evalx, evaly\
)\
} while (0)
#define EVAL_TYPE_FORMATER(a, b) \
_Generic(+(a) \
, int: _Generic(+(b) \
, int: "%d != %d" \
, long: "%d != %ld" \
, double: "%d != %f" \
) \
, long etc....
注意:使用+
運算符,您可以對您的論點應用 integer 促銷,而不是處理char
short
某些情況。 我喜歡把,
放在前面以便很好地縮進。
附言。 你可能也對我的項目yio感興趣,有了它你就可以做_assert(evalx == evaly, __LINE__, __FILE__, evalx, ",= ", evaly)
。 但它的作用與“傳遞 3 個參數”相同 - 對於每個參數,傳遞一個特殊的 function 以打印參數的類型 -> evalx, ",= ", evaly
變為六個 arguments。
問題是預處理器語義不允許它知道 C 種類型。 預處理器就是一個宏處理器,它不知道 C 語言(只是識別 C 語言標記),而是擴展充滿宏定義和宏擴展的文本文件。
當(在編譯器中)分析類型時,預處理器已經完成了編譯單元的那部分,然后它不能根據編譯器收集/生成的信息 go 返回並以不同方式擴展宏。
即使您考慮了 C 語言可以支持的所有可能類型,預處理器也不知道 C 類型是什么。 它在鏈中首先運行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.