从没见识过这么复杂的c语句,实在是看不懂,高手解释下吧
一个例程中看到下面的一段语句,以往的经验实在是看不懂,大概整理了下,例程如下:=========================================================================
void print(char x) { printf("%c",x); }
void print(int x) { printf("%d",x); }
#define LogDebug_();
#define LogDebug_1(x) print(x);
#define LogDebug_2(x, args...) print(x); LogDebug_1(args);
#define LogDebug_3(x, args...) print(x); LogDebug_2(args);
#define LogDebug_4(x, args...) print(x); LogDebug_3(args);
#define LogDebug_5(x, args...) print(x); LogDebug_4(args);
#define LogDebug_6(x, args...) print(x); LogDebug_5(args);
#define LogDebug_7(x, args...) print(x); LogDebug_6(args);
#define LogDebug_8(x, args...) print(x); LogDebug_7(args);
#define LogDebug_9(x, args...) print(x); LogDebug_8(args);
#define LogDebug_10(x, args...) print(x); LogDebug_9(args);
#define LogDebug_11(x, args...) print(x); LogDebug_10(args);
#define _NUM_ARGS2(X,X64,X63,X62,X61,X60,X59,X58,X57,X56,X55,X54,X53,X52,X51,X50,X49,X48,X47,X46,X45,X44,X43,X42,X41,X40,X39,X38,X37,X36,X35,X34,X33,X32,X31,X30,X29,X28,X27,X26,X25,X24,X23,X22,X21,X20,X19,X18,X17,X16,X15,X14,X13,X12,X11,X10,X9,X8,X7,X6,X5,X4,X3,X2,X1,N,...) N
#define NUM_ARGS(...) _NUM_ARGS2(0, __VA_ARGS__ ,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
#define LogDebug_N2(N, args...) LogDebug_ ## N(args)
#define LogDebug_N(N, args...) LogDebug_N2(N, args)
#define LogDebug(args...) do { LogDebug_N(NUM_ARGS(args), args);} while(0)
void main( void )
{
int Tmp;
int DebugData;
for(Tmp = 0;Tmp < 160; Tmp++)
{
DebugData = Tmp;
}
for(Tmp = 0;Tmp < 160; Tmp++)
{
LogDebug(Tmp, ':', DebugData);
}
}
=========================================
为了搞清楚,在vc下做了个最简单的dos模板,但是编译也通不过,提示
error C2010: “.”: 宏形参表中的意外
error C2661: “print”: 没有重载函数接受 3 个参数
以为看过的c语言书籍里没有这样的,请高手指点一下。
比如 LogDebug(150, ':', 200); 语句调用时,实际过程步骤是什么样的呢? 关键点应该在__VA_ARGS__这个宏上,你搜索一下看看。 你宏只是字符串替换而已,另外你可以搜一下 C语言的可变参数 本帖最后由 wzavr 于 2016-6-19 15:57 编辑
DevLabs 发表于 2016-6-19 15:44
关键点应该在__VA_ARGS__这个宏上,你搜索一下看看。
__VA_ARGS__简单地搜索看了下,应该还是不难,说是替换 宏定义中参数列表的最后一个参数。
有几步卡壳了,
比如 LogDebug(150, ':', 200);调用,那么经过
#define LogDebug_N2(N, args...) LogDebug_ ## N(args)
#define LogDebug_N(N, args...) LogDebug_N2(N, args)
#define LogDebug(args...) do { LogDebug_N(NUM_ARGS(args), args);} while(0)
的定义转换后,应该是:
LogDebug_150(args) 但是定义里没有 LogDebug_150 啊。
而且定义里的
#define _NUM_ARGS2(X,X64,X63,X62,X61,X60,X59,X58,X57,X56,X55,X54,X53,X52,X51,X50,X49,X48,X47,X46,X45,X44,X43,X42,X41,X40,X39,X38,X37,X36,X35,X34,X33,X32,X31,X30,X29,X28,X27,X26,X25,X24,X23,X22,X21,X20,X19,X18,X17,X16,X15,X14,X13,X12,X11,X10,X9,X8,X7,X6,X5,X4,X3,X2,X1,N,...) N
#define NUM_ARGS(...) _NUM_ARGS2(0, __VA_ARGS__ ,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
彻底晕菜了,那么多数值是怎么用的? 关键词:C99 __VA_ARGS__ wzavr 发表于 2016-6-19 15:53
__VA_ARGS__简单地搜索看了下,应该还是不难,说是替换 宏定义中参数列表的最后一个参数。
有几步卡壳了 ...
额, 你是怎么看出来
LogDebug(150, ':', 200);
替换为
LogDebug_150(args)
的.....
一步一步来吧, 原始语句:
LogDebug(150, ':', 200);
被这个宏
#define LogDebug(args...) do { LogDebug_N(NUM_ARGS(args), args);} while(0)
替换为:
LogDebug_N(NUM_ARGS(args), args)
显而易见NUM_ARGS()这个宏是用来求参数个数的, 对于你这个语句, 所以它最后将为:
LogDebug_N(3, args)
其中3为NUM_ARGS()这个宏的结果, args仍然是 150, ":", 200.
剩下的你自己替换吧, 很简单的.
在这里说一下这个3是如何求得的.
先看:
#define NUM_ARGS(...) _NUM_ARGS2(0, __VA_ARGS__, 64, 63, ......(略))
可见是一个可变参数宏, 调用了另一个宏.
再看
#define _NUM_ARGS2(X, X64, ....(略), X1, N, ...) N
重点在 N 这里, NUM_ARGS()传给它的参数将会出现在 __VA_ARGS__这里, 在原语句中是3个参数, 所以这里将占用3个位置, 后面的数字依次偏移, 本来N是被替换为0的, 当这3个数字插入后N将被替换为3, 明白了吧? 那多插入了3个参数, _NUM_ARGS2为什么不会出错呢? 因为_NUM_ARGS2()也是可变参数的, 注意末尾的 ...
DevLabs 发表于 2016-6-19 17:01
额, 你是怎么看出来
LogDebug(150, ':', 200);
替换为
感谢,简介易懂,看明白了宏的替换转变过程。
请教一下一个疑问:
_NUM_ARGS2(X,X64,X63,X62,X61,X60, 这个宏里面用的是X开头的数字,
NUM_ARGS(...) _NUM_ARGS2(0, __VA_ARGS__ ,64,63,62,61,60,59,58,5 这个宏里面直接是数字
有什么区别吗? 意义在哪里?
谢谢。
wzavr 发表于 2016-6-19 18:30
感谢,简介易懂,看明白了宏的替换转变过程。
请教一下一个疑问:
一个是宏函数的定义,一个是调用。所以X开头的那些相当于形参,而数字就是实参了。 DevLabs 发表于 2016-6-19 20:13
一个是宏函数的定义,一个是调用。所以X开头的那些相当于形参,而数字就是实参了。 ...
{:victory:}明白了,谢谢 知识贴,顶下。 很好,又学到了知识!{:lol:} 密密麻麻看的晕 本帖最后由 WM_CH 于 2016-8-6 00:20 编辑
楼主是怎么在VS上边试的?我试了一下,报的错跟你的一样。
另外,这是什么的源码。{:smile:}
mark 好厉害的样子 WM_CH 发表于 2016-8-6 00:19
楼主是怎么在VS上边试的?我试了一下,报的错跟你的一样。
另外,这是什么的源码。
楼主,求解答啊 WM_CH 发表于 2016-8-8 10:33
楼主,求解答啊
...之前加个, gujiamao_love 发表于 2016-8-9 11:10
...之前加个,
谢谢指教。{:biggrin:} 这个是不是 GUN C 语法或者 C99 支持的语法,猜测哦,不太清楚,好像这些新标准可以有比较牛掰的用法,vc 是不是不支持,linux 下好像看过这么用的比较多 WM_CH 发表于 2016-8-6 00:19
楼主是怎么在VS上边试的?我试了一下,报的错跟你的一样。
另外,这是什么的源码。
这个应该是贴子中高手说明的,gnc或者c99的语法,vc中不支持,我上面说过,测试过,无法通过编译.
这段语句也是一个初学的朋友发过来问我的,因为我稍微用过一点c,但是学得太浅薄,也是无法理解,所以发上来请高手帮助的. wzavr 发表于 2016-8-9 15:29
这个应该是贴子中高手说明的,gnc或者c99的语法,vc中不支持,我上面说过,测试过,无法通过编译.
这段语句也 ...
嗯,谢谢。
页:
[1]