2010-02-07 2 views
23

Мои самые основные знания C и процесс компиляции в последнее время стали ржавыми. Я пытался выяснить ответ на следующий вопрос, но я не мог подключить основы фазы компиляции, ссылки и предварительной обработки. Быстрый поиск в Google тоже не помог. Итак, я решил прийти к окончательному источнику знаний :) Переменные определения в заголовочных файлах

Я знаю: переменные не должны быть определены в заголовочных файлах. Его можно объявить там.

Почему: Поскольку заголовочный файл может быть включен из нескольких мест, таким образом переопределяя переменную более одного раза (компоновщик дает ошибку).

Возможная обход: Используйте заголовочные щитки в файлах заголовков и определяйте переменную в этом.

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

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

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

ответ

24

Защитник заголовка защищает вас от нескольких включений в одном исходном файле, а не из нескольких исходных файлов. Думаю, ваша проблема проистекает из понимания этой концепции.

Это не то, что защитные устройства перед процессором сохраняются во время компиляции из-за этой проблемы. Фактически во время компиляции только один исходный файл компилируется в obj, определения символов не разрешаются. Но в случае ссылки, когда компоновщик пытается разрешить определение символов, он запутывается, видя более одного определения, чтобы его флаг помечать ошибку.

+0

yikes ... это было на самом деле просто :) – Methos

10

У вас есть два файла .c. Они собираются отдельно. Каждый из них включает ваш файл заголовка. Однажды. Каждый получает определение. Они конфликтуют с временем соединения.

Традиционное решение:

#ifdef DEFINE_SOMETHING 
int something = 0; 
#endif 

Тогда вы #define DEFINE_SOMETHING в только один .c файл.

+0

Лучшее решение - это объявление в заголовке и определении только в одном файле .c. –

+0

Согласен, но я предположил, что ОП знал, что :-) – bmargulies

24

Одна вещь, которую я использовал в прошлом (когда глобальные переменные были в моде):

var.h файл:

... 
#ifdef DEFINE_GLOBALS 
#define EXTERN 
#else 
#define EXTERN extern 
#endif 
EXTERN int global1; 
EXTERN int global2; 
... 

Тогда в один .c файл (как правило, один из которых содержит main()):

#define DEFINE_GLOBALS 
#include "var.h" 

Остальные исходные файлы включают в себя обычно только «var.h».

Обратите внимание, что DEFINE_GLOBALS не является защитой заголовка, а позволяет объявлять/определять переменные в зависимости от того, определено ли оно. Этот метод позволяет использовать один экземпляр деклараций/определений.

+0

-1: Вы не отвечаете на реальный вопрос ... – 3lectrologos

+11

Хм, правда. Это просто хорошее решение. +1, чтобы компенсировать немой downvote. –

+0

@ Рихард: FYI, ни каламбур не нанят: это «в моде», а не «в моде». – Multisync

8

Защитные устройства заголовка останавливают файл заголовка, который включается несколько раз в ту же единицу перевода (то есть в тот же .c исходный файл).Они не влияют, если вы включаете файл в две или более единицы перевода.

+0

yup ... вы правы. – Methos

Смежные вопросы