Нет, все в порядке.
Видите ли, препроцессору все равно, определен ли BAR или нет вообще. Он просто заменяет string FOO на BAR в следующем исходном коде, фактически не заботясь о том, определен ли он в этой точке или нет.
Далее, в самом файле .c
(то, где начинается компиляция) включены оба заголовка, поэтому компилятор видит обе замены: FOO
-> BAR
и BAR
-> 0U
. Так что он успешно применяет их обоих.
Заголовки никогда не компилируются в одиночку, они всегда компилируются как часть файла .c
, который #include
содержит этот заголовок. (Препроцессор просто делает вид, что содержимое заголовка вставлено в место, где находится #include
.) Итак, для препроцессора ваш файл foo.c
выглядит следующим образом:
/* no inclusions */
#define FOO BAR
/* no inclusions */
#define BAR 0U
/* the rest of the file... */
/* for example: */
unsigned int i = FOO;
И компилятор после предварительной обработки видит именно это:
/* no inclusions */
/* no inclusions */
/* the rest of the file... */
/* for example: */
unsigned int i = 0U;
(не совсем уверен, возможно, препроцессор также удаляет комментарии.)
Edit:
Действительно, как упоминает @pmg, препроцессор заменяет комментарии пробелами, поэтому реальный предварительно обработанный текст, который передается в компилятор, это просто
_
_
_
_
unsigned int i = 0U;
(здесь _
обозначает пробел)