Разница в производительности препроцессора - PullRequest
0 голосов
/ 24 мая 2018

Я пытался проверить некоторые однострочные макросы, которые имеют 2 директивы препроцессора.

#define REPLACE  { \
#if EXT == 42 \
#warning "Got 42" \
#endif \
}

int main(void){
    REPLACE;
    return 0;
}

Препроцессор анализирует этот штраф:

$g++ -E includetest.cpp
# 1 "includetest.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "includetest.cpp"

int main(void){
    { #if EXT == 42 #warning "Got 42" #endif };
    return 0;
}

, что, конечно,является недопустимым кодом, так как происходит просто подстановка макроса, и похожий макрос ifdef не обрабатывается снова, даже если он выглядит как единое целое.

Теперь, если я немного изменим макрос, чтобы он выглядел как

#define REPLACE(a)  { a + 2 ; \
#if EXT == 42 \
#warning "Got 42" \
#endif \
}

int main(void){
    REPLACE(0);
    return 0;
}

Что приводит к ошибке препроцессора:

$g++ -E includetest.cpp
# 1 "includetest.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "includetest.cpp"
includetest.cpp:1:18: error: '#' is not followed by a macro parameter
 #define REPLACE(a)  { a + 2 ; \
                  ^
int main(void){
    REPLACE(0);
    return 0;
}

Почему возникает эта ошибка?Конечно, это не скомпилируется, но я хочу знать, почему добавление параметра происходит в результате ошибки синтаксического анализа препроцессора?

Люди скажут: «Вы не можете вложить другую директиву в другую», нов первом случае они также являются вложенными, почему тогда не возникает ошибка препроцессора?Или эта ответственность передана компилятору?

РЕДАКТИРОВАТЬ: я не пытаюсь достичь какой-либо функциональности как таковой, это всего лишь упражнение (бесполезно?), Чтобы понять препроцессор.

1 Ответ

0 голосов
/ 24 мая 2018

Только внутри макроса функции # имеет особое значение ( [cpp.stringize] p1 ).Стандарт гласит, что за # должен следовать аргумент функции, чего не происходит во втором случае (if, warning и endif не являются параметрами).

Ваш первыйcase допустим (вы можете иметь директивы внутри списка замены макрокоманд объекта) именно потому, что # не имеет особого значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...