Определение переменной в заголовочных файлах
Мои самые базовые знания C и процесс компиляции в последнее время стал ржавым. Я пытался выяснить ответ на следующий вопрос, но я не мог подключить основы компиляции, ссылки и предварительной обработки. Быстрый поиск в Google тоже не очень помог. Итак, я решил прийти к высшему источнику знаний :)
Я знаю: переменные не должны быть определены в .H-файлы. Его ОК, чтобы объявить их там.
почему: потому что файл заголовка может быть включен из нескольких мест, тем самым переопределяя переменную более одного раза (Компоновщик дает ошибку).
возможные решения: используйте header-guards в файлах заголовков и определите переменную в этом.
это действительно решение проблемы: нет. Потому что header-guards предназначены для фазы предварительной обработки. То есть сказать компилятору, что эта часть уже включена и не включает еще раз. Но наша ошибка множественного определения появляется в части компоновщика-намного после компиляции.
все это запутало меня в том, как работает предварительная обработка и связывание. Я думал, что предварительная обработка просто не будет включать код, если был определен символ защиты заголовка. В этом случае не следует ли также решить проблему множественного определения переменной?
Что происходит, что эти директивы предварительной обработки сохраняют процесс компиляции от переопределения символы под заголовком guards, но компоновщик по-прежнему получает несколько определений символа?
4 ответов
Header guard защищает вас от нескольких включений в одном исходном файле, а не от нескольких исходных файлов. Я думаю, ваша проблема связана с непониманием этой концепции.
Это не то, что предохранители предварительного процессора сохраняются во время компиляции от этой проблемы. Фактически во время компиляции в obj компилируется только один исходный файл, определения символов не разрешаются. Но, в случае связывания, когда компоновщик пытается разрешить определители символов, он получает смущенный видеть более одного определения casuing его, чтобы отметить ошибку.
одна вещь, которую я использовал в прошлом (когда глобальные переменные были в моде):
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.ч" нормально.
обратите внимание, что DEFINE_GLOBALS не является защитником заголовка, а позволяет объявлять/определять переменные в зависимости от того, определен ли он. Этот метод позволяет одной копии декларации / определения.
у вас есть два .c файлов. Они компилируются отдельно. Каждый из них включает файл заголовка. Однажды. Каждый получает определение. Они конфликтуют во время соединения.
обычным решением является:
#ifdef DEFINE_SOMETHING
int something = 0;
#endif
затем вы #define_something определить в единственный .файл c.
Header guards остановить файл заголовка включается несколько раз в том же подразделении, перевод (т. е. в том же .исходный файл c). Они не действуют, если файл включен в две или более единиц перевода.