了解宏扩展
回答
EDIT
3.9.6参数预扫
宏参数是完全宏扩展它们是 代入宏体之前,除非它们被字符串化或与其他令牌粘贴 。替换之后,将再次扫描包括替换参数在内的整个宏体 ,宏将扩展为 。结果是参数被扫描两次以在其中扩展 宏调用。
调用其他宏的字符串化或连接的宏。如果 参数被字符串化或级联,则不会发生预扫描。 如果您想要展开宏,然后将其展开或连接其扩展,可以通过使一个宏调用另一个执行串化或串联的宏 来实现。
举例来说,如果你有
#define AFTERX(x) X_ ## x
#define XAFTERX(x) AFTERX(x)
#define TABLESIZE 1024
#define BUFSIZE TABLESIZE
然后AFTERX(BUFSIZE)扩展到X_BUFSIZE,并XAFTERX(BUFSIZE)扩展到X_1024。 (不X_TABLESIZE。预扫描总是做了完整的扩展。)
CASE1
#define JOIN__(lhs, rhs) lhs##rhs
=>因为它有一个标记粘贴操作者,它会连接这些宏参数那些不完全宏观膨胀前取代。 - >这是一种糟糕的扩展方式,我们不知道的第一个地方,它将传递给它的参数是什么,它不会等待它的扩展,而只是将它连接起来。
因此,当您拨打JOIN__(Foo, JOIN(A,B));
时,它将不允许JOIN(A,B)
展开,并将它连接到FOOJOIN(A,B)。
CASE2 现在,在另一方面, #define JOIN_(lhs, rhs) JOIN__(lhs, rhs)
=>这里,没有标记粘贴操作,宏参数是完全宏扩展它们代入宏体之前。因此,它将允许lhs和rhs扩展并且用扩展参数JOIN__(FOO,AB)
来调用,因此现在JOIN__具有令牌粘贴操作符,它将简单地连接它的参数FOO和AB即FOOAB。这是做到这一点的适当方式。
CASE3 #define JOIN(lhs, rhs) JOIN_(lhs, rhs)
=>与CASE2相同。
希望能解释一下多级扩展范例背后的原因。
ORIGINAL 预处理运算符##提供了一种在宏扩展期间连接实际参数的方法。如果替换文本中的参数与##相邻,则该参数将被实际参数替换,将删除##和周围的空白区域,并重新扫描结果。例如,宏粘贴连接它的两个参数:
#define paste(front, back) front ## back
so paste(name, 1) creates the token name1.
我知道令牌粘贴操作符。我在询问这种多级扩展范例,而不是级联 –
@AndréFratelli:请查找“多级扩展范例”的更新答案。希望它解释你在找什么。 –
真棒回答,真的很彻底。 –
的##
记号化操作不计算(宏展开)它的参数。函数式的宏扩展do然而,评估参数,这就是为什么你得到预期(评估)输出的第一种情况。
技术上,宏JOIN_
是不必要的,因为在JOIN
lhs
和rhs
扩大JOIN__
时被评估。这将是足够的:
#define JOIN(lhs, rhs) JOIN__(lhs, rhs)
#define JOIN__(lhs, rhs) lhs##rhs
我真的找不到你错了的情况,但为什么代码会这样写呢? –
请参阅我的编辑。我包含了原始代码 –
@AndréFratelli - 谁知道?人们会做一些奇怪的事情......但我认为没有任何理由将代码编写成这种方式。 – owacoder
- 1. 定义宏扩展到了文字#
- 2. __VA_ARGS__宏扩展
- 3. Verilog宏扩展
- 4. 宏扩展
- 5. Unfamilar宏扩展
- 6. 了解Firefox扩展代码
- 7. 了解Firefox扩展结构
- 8. MSVC++ variadic宏扩展
- 9. 快速宏扩展
- 10. 超载宏扩展
- 11. 延迟宏扩展
- 12. 禁止宏扩展
- 13. C/C++宏扩展
- 14. C++宏扩展器
- 15. Clojure的宏扩展
- 16. 跟踪宏扩展
- 17. 了解_countof宏
- 18. 宏扩展到额外的宏参数
- 19. 扩展了PHP
- 20. 在递归扩展宏
- 21. C++宏扩展,调试
- 22. 预编译可扩展宏
- 23. 错误用c宏扩展
- 24. C宏扩展说明
- 25. moc中的宏扩展
- 26. 包宏扩展方法
- 27. qtcreator + gdb,扩展宏定义
- 28. 扩展C宏的类型
- 29. Eclipse宏扩展颜色
- 30. NSString内部的宏扩展
我认为,最后一个宏'JOIN __(Foo,JOIN(A,B));'应该扩展为'FooJOIN(A,B)'而不只是'FooJOIN',请澄清。 –
这是可能的。我得到'警告:函数'FooJOIN'的隐式声明在C99'中是无效的,所以我真的不知道它得到了哪些参数。但是你的意思是有道理的 –