[英]C macro, wrong argument number returned
我有以下宏:
#define CONCATENATE(arg1, arg2) arg1##arg2
#define FOR_EACH_1(what, x, ...) what(x)
#define FOR_EACH_2(what, x, ...) what(x) FOR_EACH_1(what, __VA_ARGS__)
#define FOR_EACH_3(what, x, ...) what(x) FOR_EACH_2(what, __VA_ARGS__)
#define FOR_EACH_4(what, x, ...) what(x) FOR_EACH_3(what, __VA_ARGS__)
#define FOR_EACH_5(what, x, ...) what(x) FOR_EACH_4(what, __VA_ARGS__)
#define FOR_EACH_6(what, x, ...) what(x) FOR_EACH_5(what, __VA_ARGS__)
#define FOR_EACH_7(what, x, ...) what(x) FOR_EACH_6(what, __VA_ARGS__)
#define FOR_EACH_8(what, x, ...) what(x) FOR_EACH_7(what, __VA_ARGS__)
#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N())
#define FOR_EACH_NARG_(...) FOR_EACH_ARG_N(__VA_ARGS__)
#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
#define FOR_EACH_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0
#define FOR_EACH_(N, what, x, ...) CONCATENATE(FOR_EACH_, N)(what, x, __VA_ARGS__)
#define FOR_EACH(what, x, ...) FOR_EACH_(FOR_EACH_NARG(x, __VA_ARGS__), what, x, __VA_ARGS__)
這些是我的測試用例:
// does not work as intended (with one argument)
#define SOME(x) int x;
FOR_EACH(SOME, y)
// fine with 2 and more
FOR_EACH(SOME, y1, y2);
FOR_EACH(SOME, y3, y4, y5, y6);
// works fine even for one argument
#define ONLY(x) x
int FOR_EACH(ONLY, x);
可以請某人向我解釋一下,我只是為了一個參數而錯誤地做了什么,# #define SOME(x) int x
??
用gcc -E macro.c -o macro.lol
編譯它,給出結果:
int y; int ; /* <-- that's wrong, why??? */
int y1; int y2;;
int y3; int y4; int y5; int y6;;
int x ; /* <-- works as supposed */
問題是,當你將兩個參數傳遞給FOR_EACH
(只是what
和x
)時, __VA_ARGS__
擴展為__VA_ARGS__
,並且在FOR_EACH_NARG
的調用中有一個尾隨逗號,因此它擴展為2,因此擴展了FOR_EACH_2
。
你想擺脫那個尾隨的逗號。 您可以通過使用##__VA_ARGS__
而不是__VA_ARGS__
的非標准擴展來__VA_ARGS__
此操作,僅當__VA_ARGS__
為空時才會刪除之前的逗號。 對於更符合標准的版本,您可以將x
和__VA_ARGS__
到一個參數中:
#define FOR_EACH_(N, what, ...) CONCATENATE(FOR_EACH_, N)(what, __VA_ARGS__)
#define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)
您應該已經看到編譯器的一些警告,您沒有告訴我們。
我的猜測是你的宏在這里
#define FOR_EACH_1(what, x, ...) what(x)
是錯誤的,因為它永遠不會看到__VA_ARGS__
部分。 我看到兩種治療方法
#define FOR_EACH_1(what, ...) what(__VA_ARGS__)
#define FOR_EACH_1(what, x) what(x)
使用這些宏可能會對你造成傷害的另一個原因是參數數量的計數與你習慣使用的不同。
#define MUCH(...)
#define NONE()
NONE //<- this is considered receiving no argument
MUCH //<- this receives one argument, the empty token list
如果你這樣做是為了學習預處理器,這很好:)如果你真的是這種問題的通用解決方案,你可以看看Boost(但這主要是C ++)和P99
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.