2017-02-07 15 views
1

Почему inner_LOAD_ATOM(buffer, ATOM_MAX) преобразован в scanf("%" "ATOM_MAX" "s", x), но завернутая версия isnt? Я ожидал бы, что ATOM_MAX (идентификатор) будет заменен на 10 до того, как он «пройдет» до inner_LOAD_ATOM или LOAD_LINE и сделает оболочку бесполезной. Более подробный ответ, почему необходима обертка, будет очень оценен.Macro строит предыдущий идентификатор макроса вместо его замены

#include <stdio.h> 

#define ATOM_MAX 10 
#define inner_LOAD_ATOM(x, y) scanf("%" #y "s", x)  /* inner part */ 
#define LOAD_ATOM(x, y) inner_LOAD_ATOM(x, y)   /* wrapper of inner_LOAD_ATOM */ 


int main(void) 
{ 
    char buffer[ATOM_MAX] = {0, }; 

    /* wrapped works fine */ 
    LOAD_ATOM(buffer, ATOM_MAX);   

    /* [Warning] unknown conversion 
    type character 'A' in format [-Wformat=] */ 
    inner_LOAD_ATOM(buffer, ATOM_MAX); 

    printf("%s\n", buffer); 


    return 0; 
} 

ответ

2

Важно понимать, что функции, как макросы не работают, как функции Си. Существует (почти) отсутствие стека макросотов или пересылка аргументов из одного макроса в другой. Вместо этого макрораспределение продолжается итеративно - макрос заменяется его расширением, затем расширение повторно сканируется для дальнейшего расширения макросов.

аргументы функции типа макросов полностью макро расширяются перед вставкой в ​​текст замены макроса, за исключением, где они являются операндами stringification (#) или маркера-вставка (##) оператора. Поэтому, если вы вызываете inner_LOAD_ATOM(buffer, ATOM_MAX) напрямую, ATOM_MAX не распространяется до того, как применяется оператор #.

С другой стороны, когда вы вызываете LOAD_ATOM(buffer, ATOM_MAX), макрос ATOM_MAX расширяется до LOAD_ATOM(). inner_LOAD_ATOM() не учитывается в этой точке - это всего лишь часть текста замены внешнего макроса, пока расширение LOAD_ATOM() не будет повторно сканировано для дальнейших расширений макросов.

1

Потому что на первом проходе #y получит заменен #ATOM_MAX и строковой. Таким образом, он не будет расширяться на втором проходе. Давайте просто запустить его вручную:

Первый проход:

int main(void) 
{ 
    char buffer[10] = {0, }; 

    /* wrapped works fine */ 
    inner_LOAD_ATOM(buffer, 10); // <-- Note - here it ATOM_MAX was expanded in the first pass  

    /* [Warning] unknown conversion 
    type character 'A' in format [-Wformat=] */ 
    scanf("%" "ATOM_MAX" "s", buffer); 

    printf("%s\n", buffer); 


    return 0; 
} 

Второй проход:

int main(void) 
{ 
    char buffer[10] = {0, }; 

    /* wrapped works fine */ 
    scanf("%" "10" "s", buffer);   

    /* [Warning] unknown conversion 
    type character 'A' in format [-Wformat=] */ 
    scanf("%" "ATOM_MAX" "s", buffer); // <----- Not expanded as is interpreted as string 

    printf("%s\n", buffer); 


    return 0; 
} 

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

  • Нет связанных вопросов^_^