Подтвердить что ты не робот

Определение переменной в файлах заголовков

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

файл 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 не является защитой заголовка, а позволяет разрешать/определять переменные в зависимости от того, определено ли оно. Этот метод допускает одну копию деклараций/определений.

Ответ 3

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

Обычное решение:

#ifdef DEFINE_SOMETHING
int something = 0;
#endif

Затем вы #define DEFINE_SOMETHING в только одном.c файле.

Ответ 4

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