我在一个内核代码中找到了这个宏.. http://lxr.free-electrons.com/source/arch/alpha/include/asm/io.h?v=3.0;a=arm#L140
#define IO_CONCAT(a,b) _IO_CONCAT(a,b)
#define _IO_CONCAT(a,b) a ## _ ## b
我无法理解这个含义。有人知道吗?
修改:
然后在这里返回什么
return IO_CONCAT(__IO_PREFIX,readl)(addr);
答案 0 :(得分:8)
Double hash用于将两个标记连接在一起:
#define CONCAT(a,b) a ## b
CONCAT(x, y) # Gives 'xy'
但是,如果传递的参数之一是宏本身,这种天真的实现不起作用:
#define Z y
CONCAT(x, Z) # Gives 'xZ', not 'xy' as one might expect
这就是你的问题中使用宏间接的原因:
#define CONCAT(a,b) __CONCAT(a,b)
#define __CONCAT(a,b) a ## b
#define Z y
CONCAT(x, Z) # Gives 'xy'
现在考虑一下你要问的具体例子:
return IO_CONCAT(__IO_PREFIX,readl)(addr);
这里__IO_PREFIX
显然是一个宏(Linux内核中的大写标识符通常是宏)。它在几个places中定义,其中one为:
#define __IO_PREFIX generic
现在让我们看看采取了哪些措施来扩展原始声明:
__IO_PREFIX
:
return IO_CONCAT(generic,readl)(addr);
IO_CONCAT(...)
:
return _IO_CONCAT(generic,readl)(addr);
_IO_CONCAT(...)
:
return generic_readl(addr);
答案 1 :(得分:5)
那是token pasting。它将令牌连接在一起。因此IO_CONCAT(foo,bar)
会扩展为foo_bar
。
在C99的§6.10.3.3中定义:
如果在类似函数的宏的替换列表中,紧跟在前面的参数 或者后跟一个
##
预处理令牌,该参数将被相应的替换 参数的预处理标记序列;但是,如果参数包含否 预处理令牌,参数由地标预处理令牌替换 来代替。)对于类似对象和类似函数的宏调用,在替换列表之前 重新检查更多宏名称以替换
##
预处理令牌的每个实例 在替换列表中(不是从参数中)被删除并进行前面的预处理 token与以下预处理标记连接在一起。 Placemarker 预处理令牌是专门处理的:两个场所标记的串联导致 单个地标标记预处理标记,以及地标标记与标记的连接 非地标标记预处理标记导致非地标标记预处理标记。 如果结果不是有效的预处理标记,则行为未定义。所结果的 令牌可用于进一步的宏替换。##
运营商的评估顺序 没有具体说明。
答案 2 :(得分:5)
这是预处理器token concatenation operator:
##' preprocessing operator performs token pasting. When a macro is expanded, the two tokens on either side of each
##'运算符是 合并为一个令牌,然后替换`##'和两个 原始令牌在宏观扩张中。通常两者都会 标识符,或者一个是标识符,另一个是标识符 预处理号码。粘贴后,它们会生成更长的标识符。这个 不是唯一有效的案例。也可以连接两个 数字(或数字和名称,如1.5和e3)成数字。 此外,可以通过令牌形成诸如+ =的多字符运算符 粘贴。