В чем здесь проблема? Почему n всегда равно либо 100 и 100, либо 200 и 200, как ни крути.
#include <stdio.h>
#include <iostream>
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;
}
Предпроцессор - нужен не для того, что бы писать программу времени выполнения, а для того, что бы сгенерировать код(программу) времени компиляции. Например создать две сборки 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 не совпадает с предыдущим предопределением".
Макроопределения не меняются по ходу действия. Идет обработка препроцессором. Доходит дело до блока
#ifdef A
#define N 100
#else
#define N 200
#endif
Препроцессор соображает: определено ли A? Нет? Отлично, так и запишем, что далее N меняется на 200. И дальше, когда дело доходит до n = N;, это N заменяется на уже записанное в своих каких-то внутренних таблицах препроцессора 200 независимо от других макроопределений.
В качестве иллюстрации к ответу от Harry. Возьмем простую программу, полностью аналог вашей, только вместо препроцессора - процессор:
int N;
bool b = true;
if (b)
N = 100;
else
N = 200;
b = false;
cout << N;
Что будет напечатано? По вашей логике - 200, но напечатается, естественно, 100.
Как и процессор, препроцессор С просматривает программу последовательно, вычисляя выражения по мере просмотра. Если вы изменили значение переменной, это оказывает влияние только на последующие операции.
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости