Почему мои средства защиты от компиляции не предотвращают включение нескольких определений? - PullRequest
40 голосов
/ 30 октября 2008

У меня есть заголовочный файл x.h, который включен более чем в один * .c исходный файл. В этом заголовочном файле определены некоторые структурные переменные.

Я поместил защиту от множественного включения в начало заголовочного файла как:

#ifndef X_H
#define X_H
...
..
//header file declarations and definitons.


#endif//X_H

При сборке я получаю ошибки компоновщика, связанные с несколькими определениями. Я понимаю проблему.

  1. Разве защита от многократных включений в верхней части файла заголовка, как у меня, не предотвратит множественные включения в файл заголовка xh и, таким образом, позволит избежать нескольких определений переменных, которые есть в xh? 1011 *

  2. #pragma один раз не работает на этом конкретном компиляторе, так в чем же решение? Кто-то опубликовал этот ответ на аналогичный вопрос. Кажется, это не работает для меня. Как работает это решение?

Ответы [ 6 ]

49 голосов
/ 30 октября 2008

Если компоновщик жалуется, это означает, что у вас есть определения, а не просто объявления в заголовке. Вот пример того, что было бы неправильно.

#ifndef X_H
#define X_H

int myFunc()
{
  return 42; // Wrong! definition in header.
}

int myVar; // Wrong! definition in header.

#endif

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

Заголовок:

#ifndef X_H
#define X_H

extern int myFunc();

extern int myVar; 

#endif

C Источник:

int myFunc()
{
  return 42; 
}

int myVar; 
12 голосов
/ 06 марта 2012

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

Если у вас есть определение функции f в x.h, которая включена в main.c и util.c, то это похоже на копирование и вставку определения f в main.c при создании main.o и делает то же самое для util.c, чтобы создать util.o. Тогда компоновщик будет жаловаться, и это происходит, несмотря на ваши охранники заголовка. Наличие нескольких #include "x.h" операторов в main.c возможно, конечно, из-за этих охранников.

12 голосов
/ 30 октября 2008

Использование защитных ограждений предотвращает включение заголовка одним блоком компиляции дважды. Например. если заголовок B.h включает в себя A.h, а B.cpp включает в себя A.h и B.h, все из A.h будет объявлено дважды в компиляции B.cpp, если вы не используете include guard.

Ваши включенные охранники предотвращают это, все хорошо до сих пор.

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

6 голосов
/ 17 июля 2010

Если функции невелики, вы можете использовать «inline» перед ними, и компоновщик не будет жаловаться.

2 голосов
/ 30 октября 2008

Использование защиты от нескольких включений предотвращает ошибки compiler , но вы получаете ошибку компоновщика. У вас есть определения данных в заголовочном файле, которые не используют extern?

0 голосов
/ 21 сентября 2012

Может быть X_H уже определено где-то еще? Я просто столкнулся с этой проблемой, где Xlib определяет X_H в /usr/include/X11/X.h.

Для проверки вы можете позвонить gcc -dM -E (если вы используете gcc), например, в системе сборки, которую я использую, это работает с CC=gcc CFLAGS="-dM -E" make. Если выходной файл содержит #define X_H, даже если вы удалите его из своего файла (например, используйте Y_H), он уже определен за пределами исходного кода.

...