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

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

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

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

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

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

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

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

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

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

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

Файл 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" 

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

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

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

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

 #ifdef DEFINE_SOMETHING int something = 0; #endif 

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

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

  • Могу ли я смешивать статические и общедоступные библиотеки при связывании?
  • Что такое Microsoft Visual Studio, эквивалентная опции GCC ld - whall-archive
  • VA (виртуальный адрес) и RVA (относительный виртуальный адрес)
  • Шаблон C ++, ссылка на ошибку
  • Как удалить пакет из Laravel с помощью композитора?
  • Как использовать OpenSSL в GCC?
  • ошибка LNK2038: обнаружено несоответствие для '_ITERATOR_DEBUG_LEVEL': значение '0' не соответствует значению '2' в main.obj
  • Почему порядок, в котором связаны библиотеки, иногда вызывает ошибки в GCC?
  • Давайте будем гением компьютера.