#define scope в нескольких файлах - PullRequest
13 голосов
/ 02 января 2012

У меня есть основной файл, например, так:

main_a.c:

#define MAIN_A

#include <stdio.h>
#include "shared.h"

extern int i;
int main() {
  printf("i is: %d\n", i);
  return 0;
}

Я хочу использовать определение в shared.h как здесь:

shared.h

#if defined(MAIN_A)
# define A
#endif

Таким образом, я могу объявить переменную в зависимости от того, присутствует основной файл или нет, например:

shared.c

#include "shared.h"

#if defined(A)
int i = 1;
#else
int i = 0;
#endif

Iсоздайте его, используя make-файл, который выглядит следующим образом:

Makefile:

all : a
    ./a

a : main_a.o shared.o
    gcc -o $@ $^

%.o : %.c
    gcc -c $<

Однако это печатает

i is: 0

Теперь мой вопрос: почемукажется потерянным при компиляции общего модуля?Я знаю, что основной модуль компилируется первым, поэтому определение должно быть разрешено ко времени компиляции shared.c.

У меня есть одно подозрение, что препроцессор может быть запущен в начале каждой сборки модуля ине только в начале проекта.Если это правильно, есть ли способ компилировать более одного модуля за раз, чтобы использовать препроцессор, как я пытаюсь выше?

Ответы [ 5 ]

12 голосов
/ 02 января 2012

Препроцессор запускается для каждого файла перед его компиляцией, то есть один раз для main_a.c, а затем снова независимо для shared.c. Когда shared.c компилируется, MAIN_A не определено.

Препроцессор нельзя использовать так, как вы пытаетесь, т. Е. Запоминать состояние в единицах компиляции.

Что вы можете сделать, это определить имя (например, MAIN_A), используя опцию компилятора -D в вашем Makefile, и протестировать это имя с помощью препроцессора так же, как вы это делаете сейчас. Таким образом, определение происходит на уровне проекта (в файле Makefile), а не на уровне модуля компиляции (в файле .c).

1 голос
/ 02 января 2012

Позвольте мне выполнить работу препроцессора и развернуть все ваши макросы.В main.c определяется MAIN_A, поэтому определяется A.Ничто не зависит от A в main.c, а i является внешним.

В shared.c, MAIN_A и, следовательно, A не определены, а i равно 0.

Короче говоря, препроцессор не может передавать информацию между модулями компиляции.Это хорошая практика, потому что в противном случае программы быстро стали бы нечитаемыми, и вам пришлось бы перекомпилировать все модули компиляции при изменении одного модуля (поскольку символы могли измениться).Решите проблему, установив i явно в main:

 int main() {
     i = 1;
 }

Это более многословно, но также намного понятнее читателю.Если вы хотите инкапсулировать, определите функцию InitializeShared.Если вы действительно хотите скомпилировать некоторый код как единый модуль компиляции, сделайте один из файлов заголовочным файлом, а #include - другим.

0 голосов
/ 10 апреля 2013

Определяет почти так же, как любая переменная.Если вы хотите поделиться переменной между модулями, вы должны поместить ее в заголовок.То же самое касается # define.

Однако странно использовать #ifdef, поскольку вы всегда будете иметь main.c.Вы не хотите менять код каждый раз, когда вы компилируете.Вместо этого используйте метод, описанный Адамом Зальцманом

0 голосов
/ 02 января 2012

Глобальное определение A

gcc main_a.c shared.c -DA
0 голосов
/ 02 января 2012

Да, вы правы, это совершенно отдельные единицы компиляции.

MAIN_A определяется только в main_a.c

Одна мысль, которая приходит в голову, - это объединить файлы в один модуль компиляции?

...