Заголовки включают в несколько файлов C - PullRequest
5 голосов
/ 06 августа 2011

У меня есть два файла foo.c и bar.c, которые я компилирую отдельно с gcc -c и затем связываю.Оба файла нуждаются в заголовках stdio.h и stdlib.h.

Нужно ли включать их в оба?Не чувствует себя немного излишним?Должен ли я использовать #ifdef?

Какая лучшая практика?

Ответы [ 5 ]

17 голосов
/ 06 августа 2011

Каждый файл C - это отдельная единица перевода .Другими словами, это вся отдельная программа , синтаксически полная и правильная.Таким образом, каждый файл C должен компилироваться независимо от любого другого файла C и должен содержать каждое объявление для каждого идентификатора, который он использует, независимо от того, появляются ли эти объявления также в других файлах C.С точки зрения компилятора, каждый файл C сам по себе является законченной программой (хотя и с неразрешенными ссылками).

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

Подводя итог: этонеобязательно включать одни и те же файлы в разные файлы C. Это формально необходимо.

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

2 голосов
/ 06 августа 2011

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

1 голос
/ 06 августа 2011

Файл заголовка должен (и будет) иметь оболочку #ifndef для предотвращения проблем с этим (проблема на самом деле с циклическим включением - вы включаете -> foo.h включает в себя bar.h bar.h включает в себя foo.h).

В вашем случае «дублирующее» включение действительно необходимо (для прототипов функций, определений структуры), поскольку (как вы сказали) оба файла компилируются отдельно.Процесс компиляции foo.c ничего не знает о компиляции bar.c.

0 голосов
/ 06 августа 2011

Да, вы должны включить их обоих.Я в основном работаю в C ++ и стараюсь включать файлы в мои файлы .cpp всякий раз, когда это возможно, и в мои файлы .h, только если это необходимо.Это часто означает использование некоторого типа прямой ссылки в файле .h.

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

Каждый файл .h, который вы пишете, должен иметь то, что известно как «включить охрану».Это операторы #ifdef, которые не позволяют включать заголовок более одного раза.Вы заметите, что у тех, кого вы упомянули, уже есть охранники.Но убедитесь, что вы поместили их в свои foo.h и bar.h тоже.

0 голосов
/ 06 августа 2011

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

...