简体   繁体   English

C宏示例

[英]C macro example

I come across this C macro: 我遇到了这个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),                 \
    }

I vaguely understand that it tries to define a struct of type cmd from a bunch of input params of the macro. 我模糊地理解,它试图从一堆宏的输入参数中定义cmd类型的结构。 But I don't really get what these two lines mean: 但是我并没有真正理解这两行的含义:

 __cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden\
 __attribute__((used)) __attribute__((section("__cmd")))     = {     \

Can someone explain? 有人可以解释吗? thanks. 谢谢。

The token ## is used to concatenate the arguments. 令牌##用于连接参数。

Eg 例如

#define CONCAT(A, B) A ## B

int a = CONCAT(My, Function)();

That is equivalent to saying: 这相当于说:

int a = MyFunction();

You can see further details at http://en.cppreference.com/w/c/preprocessor/replace . 您可以在http://en.cppreference.com/w/c/preprocessor/replace上查看更多详细信息。

Given the macro definition you posted, a call of 给定您发布的宏定义,调用

__COMMAND( Section, Symname, Name, Args, Nlccmd, Flags, Hidden, Idby, Handler, Help, Sel );

will resolve to: 将解决:

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 ),
};

The line 线

static struct cmd

starts the definition of a static object of type struct cmd (declared elsewhere). 开始定义struct cmd类型的static对象(在其他地方声明)。

The macro line 宏线

__cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden\

uses the arguments of the macro to concatenate the identifier of that struct cmd (obviously in hopes that it will be unique). 使用宏的参数来连接该struct cmd的标识符(显然希望它是唯一的)。

Others have linked to the relevant documentation of the ## operator; 其他人已经链接到##运算符的相关文档; I won't steal from them. 我不会从他们那里偷东西。

At this point it should be noted that identifiers starting with __ are reserved for the implementation (of the compiler and the standard library), so strictly speaking this makes the program non-conforming with the language standard. 此时,应注意,以__开头的标识符是为(编译器和标准库的)实现保留的,因此严格来说,这会使程序与语言标准不一致。 (Not that it matters because the use of __attribute__ below is non-portable anyway.) (这并不重要,因为下面的__attribute__的使用还是不可移植的。)

The line 线

__attribute__((used)) __attribute__((section("__cmd"))) = { \

sets "attributes" of the struct. 设置结构的“属性” This is a compiler-specific syntax extension. 这是特定于编译器的语法扩展。 From the GCC docs: 从GCC文档:

used 用过的

This attribute, attached to a variable with static storage, means that the variable must be emitted even if it appears that the variable is not referenced. 该属性附加到具有静态存储的变量中,意味着即使看起来未引用该变量,也必须发出该变量。

section ("section-name") 部分(“部分名称”)

Normally, the compiler places the objects it generates in sections like data and bss. 通常,编译器将其生成的对象放在数据和bss之类的部分中。 Sometimes, however, you need additional sections, or you need certain particular variables to appear in special sections, for example to map to special hardware. 但是,有时您需要其他部分,或者需要某些特定变量以显示在特殊部分中,例如,映射到特殊硬件。 The section attribute specifies that a variable (or function) lives in a particular section. section属性指定变量(或函数)存在于特定节中。 [...] [...]

It then goes on to initialize the struct members with the arguments passed to the macro. 然后,它继续使用传递给宏的参数来初始化结构成员。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM