Страницы

Поиск по вопросам

воскресенье, 26 января 2020 г.

Директивы препроцессора #ifdef #define и #undef

#cpp #препроцессор


В чем здесь проблема? Почему n всегда равно либо 100 и 100, либо 200 и 200, как ни крути.

#include 
#include 

using namespace std;

#ifdef A
    #define N 100
#else  
    #define N 200
#endif


int main()
{
    #define A
    int n = N;
    cout << n << endl;
    #undef A
    #define B
    n = N;
    cout << n << endl;
    #undef B
    return 0;
}

    


Ответы

Ответ 1



Предпроцессор - нужен не для того, что бы писать программу времени выполнения, а для того, что бы сгенерировать код(программу) времени компиляции. Например создать две сборки debug и release. Или в вашем случае два модуля, один с N=100 и второй N=200. Всё верно. Или так или так, но не две одновременно (условно). Предпроцессор не умеет делать "процедуры и функции" процессинга в широком смысле (функции аргумента - существуют). Т.е. реальный код генерируется за один проход. Если один раз сделано #define N 100 то N не изменит значение до тех пор пока снова не встретится define N или undef N (зачёркиваем "условно"). Другого способа повлиять - нету. В коде все директивы выполняются последовательно. Т.е. код #ifdef A #define N 100 #else #define N 200 #endif int main() { #define A int n = N; cout << n << endl; #undef A #define B n = N; cout << n << endl; #undef B return 0; } Является "виртуальным" в реальности предпроцессор делает из него такой код // N = 200 int main() { // A задано, N без изменений int n = 200; cout << n << endl; // B задано, А не_задано, N без изменений n = 200; cout << n << endl; return 0; } Но на самом деле всё "условно", что бы ваш код работал, вам его нужно поправить так вставив фрагмент ниже, или сохранить это фрагмент в файл например def_A.h c таким кодом #ifdef A #define N 100 #else #define N 200 #endif Условно, потому что есть способ заставить перегенерировать директивы. Просто нужно сказать предпроцессору - хочу перезадать N вот так например int main() { #define A #include "def_A.h" //#ifdef A // #define N 100 //#else // #define N 200 //#endif int n = N; cout << n << endl; #undef A #define B #include "def_A.h" //#ifdef A // #define N 100 //#else // #define N 200 //#endif n = N; cout << n << endl; #undef B return 0; } Вставил комментраием то, что делает директива include. Приводить какой код сгенерирует предпроцессор не буду, думаю это очевидно. И как последний штрих, допишите перед #define N 100, а лучше перед #ifdef A директиву #undef N. Это не обязательно, это уберет warning или hint с уведомлением что "переопределение N не совпадает с предыдущим предопределением".

Ответ 2



Макроопределения не меняются по ходу действия. Идет обработка препроцессором. Доходит дело до блока #ifdef A #define N 100 #else #define N 200 #endif Препроцессор соображает: определено ли A? Нет? Отлично, так и запишем, что далее N меняется на 200. И дальше, когда дело доходит до n = N;, это N заменяется на уже записанное в своих каких-то внутренних таблицах препроцессора 200 независимо от других макроопределений.

Ответ 3



В качестве иллюстрации к ответу от Harry. Возьмем простую программу, полностью аналог вашей, только вместо препроцессора - процессор: int N; bool b = true; if (b) N = 100; else N = 200; b = false; cout << N; Что будет напечатано? По вашей логике - 200, но напечатается, естественно, 100. Как и процессор, препроцессор С просматривает программу последовательно, вычисляя выражения по мере просмотра. Если вы изменили значение переменной, это оказывает влияние только на последующие операции.

Комментариев нет:

Отправить комментарий