2015-10-19 2 views
1

Я наткнулся на этом C макрос: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 от связки ввода PARAMS макроса. Но я не понимаю, что означают эти две линии:

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

Может кто-нибудь объяснить? Благодарю.

+1

Это приложение оператора точечного приклеивания (##). Взгляните сюда - https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html – Samboy786

ответ

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

Учитывая определение макроса Вы отправляли сообщение, вызов

__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" из структуры. Это расширение для синтаксиса, специфичное для компилятора. Из ССАГПЗ Документах

используется

Этот атрибут, прикрепленный к переменной со статической памяти, означает, что переменная должна быть излучается даже если окажется, что переменная не ссылается.

раздела («раздел имя»)

Обычно компилятор помещает объекты, которые он генерирует, как в разделах данных и ПБС. Иногда, однако, вам нужны дополнительные разделы, или вам нужно, чтобы определенные специальные переменные отображались в специальных разделах, например, для сопоставления с специальным оборудованием. Атрибут section указывает, что переменная (или функция) живет в определенном разделе. [...]

Затем он инициализирует элементы структуры аргументами, переданными макросу.

Смежные вопросы