至于处理更大的项目,我想引入一些自己的类型(例如myType
)。 “匆匆进入” - 方法是将这些typedef放入标题(比如说myType.h
),以及一系列处理这些类型的函数。
如果我在某处使用新类型,我将myType.h
包含在我的源文件中。细
但是如果我想在函数签名中将某个新类型用作参数,我需要将myType.h
包含在包含该函数的模块的头中。使用一个或另一个typedef,这对我来说似乎没问题,但是我拥有的类型越多,我需要的头文件中包含的内容越多,可能包括更多标头,同时使用包含其他自己类型的类型。这导致我称之为“依赖地狱”。
是否有一种聪明,时尚,最佳实践,解决这种困境的解决方法?
我知道有可能将这些类型作为void-pointer传递,然后将它们放回到函数内部,但随后我从编译器中放弃了重要的类型检查。
Weher,extern
被认为是最糟糕的做法......
修改
详细说明:
myType.h
:
#include "otherType.h"
typedef struct {
char Name[32];
int Size;
otherType someType;
} myType;
processSomeHow(myType _myType, int NewSize);
otherType.h
#define SOME_CONST 32
typedef struct { [...] } otherType;
someModule.h
:
#include "myType.h"
int specialProcessSomeHow(myType _myType);
someModule.c
:
int specialProcessSomeHow(myType _myType)
{
int Size = 64;
return(processSomeHow(_myType, Size));
}
现在我将otherType.h
间接包含在someModule.h
中,更糟糕的是,我将其包含在每个模块中,包括someModule.h
。现在我到处都有一个SOME_CONST
,很难弄清楚它来自哪里。我必须保留两个包括树。
答案 0 :(得分:1)
就像在gtk库中一样,您可以使用一个头文件并根据需要将其拆分。
type.h
- myType.h
-- someType.h
- otherType.h
- List item
和你的CONST问题: 如果你只需要一个c.file。不要在HeaderFile中使用它们。 您可以将它们命名为“MY_TYPE_SOME_CONST”或“OTHER_TYPE_SOME_CONST”;
//编辑:
说清楚:只需添加'this.h'文件并命名即可。
#ifndef TYPE_H_
#define TYPE_H_
#include myType.h
#include someType.h
#include otherType.h
#endif /* TYPE_H_ */
现在您可以为需要类型的每个文件使用“#include this.h”。 (this.h不是真实的,将其命名为独特的东西)
答案 1 :(得分:0)
您可以(也可能应该)使用自定义类型的前向声明。详情请见typedef stuct with forward declaration in C
你的接口(标题)应该有不完整的类型(即指向自定义类型的指针),在源代码(c文件)中你应该包含My_Type.h
。
答案 2 :(得分:0)
你不必要地担心:没有'依赖地狱',正是因为你给编译器提供了完成它所需要的所有信息。
这是我的规则:
因此,如果b.h使用a.h中的类型,那么b.h必须#include "a.h"
。如果b.c
使用a.h
中的函数,但b.g
不使用其中的类型,那么b.c
应该#include a.h。
extern
关键字,因为IIRC现代编译器正确地推断出这一点。将extern
用于全局变量可能会让人不满意
原因。
全局命名空间的混乱。 C ++命名空间解决了这个问题,但在C语言中,您必须对所有全局类型,函数和#defines
使用命名约定。选择适合您的约定:我看到团队成功地为每个源文件使用LETTER-DIGIT-DIGIT前缀,因此foo.h
可能会成为(例如)B04_foo.h
,并且所有函数/类型得到相同的B04_
前缀。它有点粗糙,但它的工作原理。正如我所说,选择一个适合你的。