如果我有一个带有结构的源.c文件:
struct a {
int i;
struct b {
int j;
}
};
如何在另一个文件(即func.c
)中使用此结构体?
我应该创建一个新的头文件,在那里声明结构并将该头包含在func.c
中吗?
还是应该在头文件中定义整个结构,并将其包含在source.c
和func.c
中?如何在两个文件中都将结构声明为extern
?
我应该typedef
吗?如果是,如何?
如果这个结构要被其他文件func.c使用,该怎么办
当一个类型在文件(即func.c文件)中使用时,它必须是可见的。最糟糕的方法是将它复制粘贴到每个需要的源文件中
正确的方法是将其放在头文件中,并在需要时包含此头文件。
我们应该打开一个新的头文件,在那里声明结构,并将该头包含在func.c中吗
这是我更喜欢的解决方案,因为它使代码高度模块化。我会把你的结构编码为:
#ifndef SOME_HEADER_GUARD_WITH_UNIQUE_NAME
#define SOME_HEADER_GUARD_WITH_UNIQUE_NAME
struct a
{
int i;
struct b
{
int j;
}
};
#endif
我会把使用这种结构的函数放在同一个头中(在"语义上"是其"接口"的一部分的函数)。
通常,我可以在结构名称之后命名文件,然后再次使用该名称来选择头保护定义。
如果需要使用指向结构的指针来声明函数,则不需要完整的结构定义。一个简单的正向声明,如:
struct a ;
这就足够了,它减少了耦合。
或者我们可以在头文件中定义总结构,并将其包含在source.c和func.c中吗
这是另一种方式,在某种程度上更容易,但模块化程度更低:一些只需要您的结构就可以工作的代码仍然必须包括所有类型。
在C++中,这可能会导致有趣的复杂性,但这超出了主题(没有C++标记),所以我不会详细说明。
那么如何在两个文件中将该结构声明为extern
也许我看不出这一点,但Greg Hewgill在他的帖子中有一个很好的答案。如何在c中的多个文件使用的头中声明一个结构?。
那我们怎么打字好吗
- 如果您使用的是C++,请不要使用
- 如果你正在使用C,你应该这样做
原因是C结构管理可能很麻烦:你必须在使用它的任何地方声明struct关键字:
struct MyStruct ; /* Forward declaration */
struct MyStruct
{
/* etc. */
} ;
void doSomething(struct MyStruct * p) /* parameter */
{
struct MyStruct a ; /* variable */
/* etc */
}
而typedef将使您能够在不使用struct关键字的情况下编写它。
struct MyStructTag ; /* Forward declaration */
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
void doSomething(MyStruct * p) /* parameter */
{
MyStruct a ; /* variable */
/* etc */
}
重要的是您仍然为结构保留一个名称。写作:
typedef struct
{
/* etc. */
} MyStruct ;
将只创建一个具有typedef-ed名称的匿名结构,并且您将无法转发声明它
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
因此,您可以在任何地方使用MyStruct,以避免添加struct关键字,并且在typedef不起作用时(即正向声明)仍然使用MyStructTag
编辑:
更正了关于C99结构声明的错误假设,正如Jonathan Leffler正确地指出的那样。
编辑2018-06-01:
Craig Barnes在他的评论中提醒我们,您不需要为结构"保留单独的名称;标签";名称及其";typedef";名字,就像我上面为了清楚起见所做的那样。
事实上,上面的代码可以写成:
typedef struct MyStruct
{
/* etc. */
} MyStruct ;
IIRC,这实际上就是C++在幕后对其更简单的结构声明所做的,以使其与C:兼容
// C++ explicit declaration by the user
struct MyStruct
{
/* etc. */
} ;
// C++ standard then implicitly adds the following line
typedef MyStruct MyStruct;
回到C,我看到了这两种用法(单独的名字和相同的名字),据我所知,没有一种有缺点,所以如果你不使用C separate",那么使用相同的名字会让阅读变得更简单;名称空间";用于结构和其他符号。
对于要在多个源文件中使用的结构定义,您应该将其放在头文件中。然后将该头文件包含在任何需要该结构的源文件中。
extern
声明不用于结构定义,而是用于变量声明(即,具有您定义的结构类型的某些数据值)。如果您想在多个源文件中使用相同的变量,请在头文件中声明为extern
,如:
extern struct a myAValue;
然后,在一个源文件中,定义实际变量:
struct a myAValue;
如果您忘记执行此操作,或者不小心在两个源文件中定义了它,链接器会让您知道这一点。
a.h:
#ifndef A_H
#define A_H
struct a {
int i;
struct b {
int j;
}
};
#endif
现在,您只需要将.h包含到要使用此结构的文件中。