使用#ifndef #define #endif对C头文件进行最佳练习

时间:2010-05-30 16:06:36

标签: c coding-style header

关于以下“模式”的最佳做法是什么?

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

我应该如何命名#define指令中的标题?我见过BLAFOO_H__BLAFOO_H_BLAFOO_H_等所有内容。

5 个答案:

答案 0 :(得分:22)

将它们命名为BLAFOO_H(我个人使用BLAFOO_H_,其中BLAFOO是头文件名。)

确保您的BLAFOO不与其他文件/库等冲突。你正在使用,例如让您的项目和/或模块名称成为该名称的一部分。

_开头的标识符是为实现/编译器保留的,所以不要使用它。

答案 1 :(得分:5)

我使用 UUID ,这是我保证#define不与其他人发生冲突的保证。我已经在某个地方看到它,并决定也使用它。

我的模式是这样的:__<filename>_H_<uuid>__

例如。 #define __TYPES_H_79057761_16D6_478A_BFBC_BBF17BD3E9B9__表示名为types.h

的文件

答案 2 :(得分:3)

唯一真正的要求是它不会与另一个对其文件使用相同名称的项目冲突。对于我见过的所有项目,它通常完全量化命名空间(或文件用于C的任何文件夹)以及项目名称。有时它也包括创建文件的日期。

因此,如果您今天在DEF文件夹中处理项目ABC,那么您可以这样做:

#ifndef ABC_DEF_BLAFOO_H_05_30_2010

这不太可能与任何事情发生冲突。

答案 3 :(得分:3)

与其他C风格的问题一样,只需一致。您无法知道某人可能在将来与您的程序链接的每个库的命名空间。为什么?其中许多尚未编写:)

因此,它不是包含警卫的问题,而是首先要对标题命名的问题。

我可能会想出一些很酷的新字符串实用程序,并将标题命名为strutil。这是一个坏主意,因为(当然)其他人已经提出了很酷的新字符串实用程序,并将标题命名为相同。

所以,我将我的名字命名为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);

如果您经历了寻找唯一命名空间的麻烦,请务必使用它:)

答案 4 :(得分:1)

只要它不可能在其他任何地方使用,它并不重要。我通常使用像BLAFOO_H_INCLUDED这样的东西。