我遇到过这个C宏:
#define __COMMAND(_section, _symname, _name, _args, _nlcmd, _flags, _hidden, _idby, _handler, _help, _sel)\
static struct cmd \
__cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden\
__attribute__((used)) __attribute__((section("__cmd"))) = { \
.name = (_name), \
.args = (_args), \
.cmd = (_nlcmd), \
.nl_msg_flags = (_flags), \
.hidden = (_hidden), \
.idby = (_idby), \
.handler = (_handler), \
.help = (_help), \
.parent = _section, \
.selector = (_sel), \
}
我模糊地理解它试图从宏的一堆输入参数中定义类型cmd
的结构。但我真的不明白这两行是什么意思:
__cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden\
__attribute__((used)) __attribute__((section("__cmd"))) = { \
有人可以解释一下吗?感谢。
答案 0 :(得分:5)
令牌##
用于连接参数。
E.g。
#define CONCAT(A, B) A ## B
int a = CONCAT(My, Function)();
这相当于说:
int a = MyFunction();
您可以在http://en.cppreference.com/w/c/preprocessor/replace了解更多详情。
答案 1 :(得分:1)
根据您发布的宏定义,调用
__COMMAND( Section, Symname, Name, Args, Nlccmd, Flags, Hidden, Idby, Handler, Help, Sel );
将解决:
static struct cmd
__cmd_Symname_Handler_Nlcmd_Idby_Hidden
__attribute__((used)) __attribute__((section("__cmd"))) = {
.name = (Name),
.args = (Args),
.cmd = (Nlcmd),
.nl_msg_flags = (Flags),
.hidden = (Hidden),
.idby = (Idby),
.handler = (Handler),
.help = (Help),
.parent = (Section),
.selector = (Sel ),
};
该行
static struct cmd
开始定义static
类型为struct cmd
的对象(在别处声明)。
宏观线
__cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden\
使用宏的参数来连接struct cmd
的标识符(显然希望它是唯一的)。
其他人已与##
运营商的相关文档相关联;我不会偷他们。
此时应注意,以__
开头的标识符保留用于(编译器和标准库)的实现,因此严格来说这会使程序不符合语言标准。 (这并不重要,因为无论如何使用下面的__attribute__
都是不可移植的。)
该行
__attribute__((used)) __attribute__((section("__cmd"))) = { \
设置结构的"attributes" 。这是特定于编译器的语法扩展。来自GCC文档:
使用
此属性附加到具有静态存储的变量,意味着即使看起来未引用该变量,也必须发出该变量。
部分(“section-name”)
通常,编译器将它生成的对象放在data和bss等部分中。但是,有时您需要其他部分,或者需要某些特定变量出现在特殊部分中,例如映射到特殊硬件。 section属性指定变量(或函数)存在于特定节中。 [...]
然后继续使用传递给宏的参数初始化struct成员。