目前我正在为通信协议编写一个库。对于这个任务,我需要这个结构:
typedef struct _C8B10 {
unsigned int six :6;
unsigned int four :4;
} C8B10;
但我应该在哪里定义它?我有一个'main'* .h文件,包含在所有其他库中。每个lib的* .c文件仅包含'parent'* .h-file。结构类似于树:
Main.h
Main.c
Child.h
Child.c
Child2.h
Child2.c
....
孩子们总是包含父母的Main.h
和child.c
。但是在一个库中我得到错误,没有定义类型。
目前它在Main.h文件中声明。但是把它放进去的最佳位置在哪里?
答案 0 :(得分:2)
无论你做什么,都应该将结构标记从_C8B10
更改为不会在为实现保留的命名空间上进行践踏的内容。
ISO / IEC 9899:2011
7.1.3保留标识符
¶1每个标头声明或定义其相关子条款中列出的所有标识符,和 可选地声明或定义其关联的未来库方向中列出的标识符 子条款和标识符,它们总是保留用于任何用途或用作文件 范围标识符。
- 所有以下划线和大写字母或其他字母开头的标识符 下划线总是保留用于任何用途 - 始终保留以下划线开头的所有标识符作为标识符 在普通名称和标签名称空间中都有文件范围。
以下划线开头的名称存在风险;他们在那里为系统库的提供者。显然,如果你的图书馆是实施的一部分,这不适用于你,但我认为你不可能提出问题是否属于这种情况。
如果是我的代码,我只需删除下划线:typedef struct C8B10 { ... } C8B10;
很好(typedef
名称在普通标识符命名空间中,结构标记在tags命名空间中,两个不要冲突。)
您的图表与大多数人通常编写此类图表的方式相反。源代码包含标题,因此可能将其图示为:
main.c
main.h
child1.c
child1.h
child2.c
child2.h
然而,这不可能是整个故事。您创建一个标题来共享源文件之间的声明;一个文件只包含一个标题并不是绝对必要的(虽然创建这样的文件可能有合法的原因)。文件main.c
使用child1.c
中定义的某些函数(和类型 - 可能是宏甚至全局变量,消除思想)或child1.c
中的代码使用main.c
中的材料{1}}(或可能两者)。因此,main.c
应包含child1.h
或child1.c
应包含main.h
或两者。
您需要考虑使用库的另一个方面是“库的客户端如何使用代码?”这很关键。客户端代码需要什么标头?客户端代码需要哪些功能?客户端代码是否需要任何类型定义?客户端代码是否需要访问C8B10结构的成员,或者他们是否只需将其视为不透明类型?
您的外部标题 - 库的客户端使用的标题 - 应该尽可能小,但是自包含。我们假设外部头是c8b10.h
。如果客户端源代码具有#include "c8b10.h"
作为源文件中的第一个或唯一标头,则标头中的代码应该编译。例如,如果您的界面使用size_t
,则需要#include <stddef.h>
中的c8b10.h
。
在您的情况下,我希望您的C8B10
结构应在main.h
中定义,而child1.c
和child2.c
都应包含main.h
。 main.c
可能还应包含child1.h
和child2.h
。 main.h
应包含外部c8b10.h
标头,因此实际上每个文件都包含该标头。
main.c
main.h
c8b10.h
child1.h
child2.h
child1.c
main.h
c8b10.h
child1.h
child2.c
main.h
c8b10.h
child2.h
child2.c
是否需要包含child1.h
以及child1.c
是否需要包含child2.h
取决于代码的编写方式以及每个文件提供的服务其中。
您可能会发现只有两个标头更为明智 - 外部c8b10.h
标头和一个内部标头c8b10-private.h
。 c8b10-private.h
标头将包含在库中的每个源文件中。它将包含的第一个标头是外部c8b10.h
标头(以帮助自动检查c8b10.h
标头是否自包含)。 c8b10-private.h
标头将对应main.h
,child1.h
和child2.h
的合并,减去c8b10.h
中定义的外部可访问内容。这导致:
main.c
c8b10-private.h
c8b10.h
child1.c
c8b10-private.h
c8b10.h
child2.c
c8b10-private.h
c8b10.h
要记住的关键点是标题用于源文件之间的通信。其余部分主要是自动完成的。
答案 1 :(得分:1)
头文件通常像Java的接口一样使用,因为头文件定义了实现之外可用的信息。
如果结构应该在实现之外可用,请在标头中定义它,否则在.c文件中将其定义一次,该文件包含在其他.c文件中。