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

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

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

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

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

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

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

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

24
задан Brian Tompsett - 汤莱恩 21 February 2016 в 18:06
поделиться

4 ответа

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

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

24
ответ дан 28 November 2019 в 22:33
поделиться

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

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

26
ответ дан 28 November 2019 в 22:33
поделиться

Думаю, этот макрос делает именно то, что вы хотите:

#define DYN_IF(dest_type, dest_ptr, src_ptr)                                 \
    if((src_ptr).isType<dest_type>())                                        \
        if(int dest_type##dest_ptr = 1)                                      \
        for(Ptr<dest_type> dest_ptr = (src_ptr).convertAs<dest_type>();      \
            dest_type##dest_ptr;                                             \
            dest_type##dest_ptr=0)                                           

Использование:

ObjectPtr ptr;
DYN_IF(Foo, foo_ptr, ptr) { 
    // foo_ptr is Ptr<Foo>
}
DYN_IF(Bar, bar_ptr, ptr)  // Works without braces too for single statement 
    // bar_ptr is Ptr<Bar>

Я бы не рекомендовал такого рода вещи в коде, который предназначен для чтения кем-то другим, но так как вы упомянули слово «макро»...

Кроме того, я бы не стал делать вид, что это имеет отношение к совпадению образцов в стиле Haskell/OCaml. Проверьте Scala, если вы хотите язык, который имеет семантику, похожую на C++ (ну, вид) и истинное совпадение образца.

-121--3780273-

cpulimit - это инструмент, который делает что-то подобное. Периодически работает kill -STOP и kill -CONT процесс, который приводит к тому, что он работает медленнее (при усреднении во времени).

-121--3713289-

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

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

#ifdef DEFINE_SOMETHING
int something = 0;
#endif

Тогда вы # определяете DEFINE_SOMETHING в только один файл .c.

10
ответ дан 28 November 2019 в 22:33
поделиться

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

8
ответ дан 28 November 2019 в 22:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: