передовой опыт работы с заголовочными файлами C с помощью #ifndef #define #endif - PullRequest
13 голосов
/ 30 мая 2010

Что касается наилучшей практики в отношении следующего «паттерна»?

#ifndef BLAFOO_H
#define BLAFOO_H
/* ...
 * ...
 */
#endif /* BLAFOO_H */

как мне назвать заголовок в директиве #define? я видел все от сказанного BLAFOO_H до __BLAFOO_H до _BLAFOO_H_ и т. д.

Ответы [ 5 ]

22 голосов
/ 30 мая 2010

Назовите их BLAFOO_H (лично я использую BLAFOO_H_, где BLAFOO - имя файла заголовка).

Убедитесь, что ваш BLAFOO не конфликтует с другими файлами / библиотеками / и т.д. вы используете, например, ваш проект и / или имя модуля должны быть частью этого имени.

Идентификаторы, начинающиеся с _, зарезервированы для реализации / компилятора, поэтому не используйте их.

5 голосов
/ 30 мая 2010

Я использую UUID , что является моей гарантией того, что #define не конфликтует с другими. Я видел это где-то и решил использовать это также.

Мой шаблон выглядит так: __<filename>_H_<uuid>__,

например. #define __TYPES_H_79057761_16D6_478A_BFBC_BBF17BD3E9B9__ для файла с именем types.h

3 голосов
/ 30 мая 2010

Как и в случае с другими вопросами стиля C, просто будьте последовательными . Вы не сможете узнать пространство имен каждой библиотеки, которую кто-то может связать с вашей программой в будущем. Зачем? Многие из них еще не написаны:)

Таким образом, вопрос не в том, чтобы включить охрану, а в том, как назвать заголовок.

Я мог бы придумать несколько крутых новых утилит для работы со строками и назвать структуру заголовка. Это плохая идея, потому что (конечно) кто-то еще придумал классные новые строковые утилиты и назвал заголовок таким же.

Итак, я называю мой post_strutils.h и:

#ifndef POST_STRUTILS_H
#define POST_STRUTILS_H
/* code */
#endif

Я могу даже назвать это post_str_utils.h и правильно определить охрану включения, потому что я знаю, что у меня очень распространенная фамилия. Найти пространство имен иногда сложно. Простое использование одного не дает гарантии, что кто-то еще выполнил поиск до того, как выпустить что-то на волю. Будьте как можно более уникальными.

В зависимости от того, где кто-то говорит своему компилятору искать заголовки, в игру вступают не только конфликты пространства имен, но и имена файлов. Сделайте все возможное, чтобы уникально назвать заголовок , а затем напишите включающий охранник, чтобы соответствовать ему. Кто-то может захотеть #error, если заголовок был включен несколько раз, хотя бы для того, чтобы вырезать ненужные директивы #include, используя UUID, что делает это непонятным, поскольку он не совпадает (или даже напоминает) ) имя файла заголовка, о котором идет речь. Это также затрудняет написание grep/awk (или аналогичных) скриптов с поддержкой lint.

Я не говорю, что вы должны называть каждую библиотеку / модуль именем себя, но позаботьтесь о том, чтобы имена публичных заголовочных файлов были уникальными. Быстрая конференция с поисковой системой скажет вам, если вы попали в неиспользуемое пространство имен. Пожалуйста, позвольте включенным охранникам соответствовать (или, по крайней мере, близко походить) на заголовок. Опять же, последовательность высоко оценивается. Из вашего примера я бы ожидал:

int blahfoo_init(void);
double blahfoo_getval(blahfoo_t *blah);

Если вы не можете найти уникальное пространство имен, обязательно используйте его:)

3 голосов
/ 30 мая 2010

Единственным реальным требованием является то, что он не будет конфликтовать с другим проектом, который использует то же имя для своего файла. Для всех проектов, которые я видел, он обычно полностью определяет пространство имен (или любую папку, в которой находится файл для C) вместе с именем проекта. Иногда он также включает дату создания файла.

Итак, если вы сегодня работаете над проектом ABC в папке DEF, вы можете сделать:

#ifndef ABC_DEF_BLAFOO_H_05_30_2010

И вряд ли это будет конфликтовать с чем-либо.

1 голос
/ 30 мая 2010

Это на самом деле не имеет значения, если его вряд ли можно использовать где-либо еще. Я обычно иду с чем-то вроде BLAFOO_H_INCLUDED.

...