双哈希用于将两个标记连接在一起:
#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'
UPD。
现在考虑您要询问的具体示例:
return IO_CONCAT(__IO_PREFIX,readl)(addr);
这里__IO_PREFIX
显然是一个宏(Linux 内核中的大写标识符通常是宏)。它在几个地方定义,其中之一是:
#define __IO_PREFIX generic
现在让我们看看采取了哪些步骤来扩展原始语句:
- 展开
__IO_PREFIX
:
返回 IO_CONCAT(通用,readl)(地址);
- 展开
IO_CONCAT(...)
:
返回_IO_CONCAT(通用,readl)(地址);
- 展开
_IO_CONCAT(...)
:
返回generic_readl(地址);