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

Мои самые базовые знания 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). Они не действуют, если файл включен в две или более единиц перевода.