struct a {
int i;
struct b {
int j;
}
};
这个结构体应该如何在另一个文件(例如func.c
)中使用?
我应该创建一个新的头文件,在那里声明结构体并在func.c
中包含该头文件吗?
还是应该在头文件中定义整个结构体,并在source.c
和func.c
中都包含它?如何在两个文件中将结构体声明为extern
?
我应该使用typedef
吗?如果是,怎么做?
当一个类型在文件中被使用时(例如 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 ;
这样就足够了,而且它减少了耦合。
这是另一种方式,相对容易一些,但不太模块化:某些仅需要您的结构才能工作的代码仍然必须包括所有类型。
在C ++中,这可能会导致有趣的复杂性,但这超出了主题(没有C ++标签),因此我不会详细说明。
我看不出重点所在,但Greg Hewgill在他的帖子How to declare a structure in a header that is to be used by multiple files in 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名称的匿名结构体,您将无法进行前向声明。因此,请遵循以下格式:
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
更正了关于C99结构体声明的错误假设,如Jonathan Leffler所指出的那样。
Craig Barnes 在他的评论中提醒我们,您不需要为结构体“标签”名称和其“typedef”名称保留单独的名称,就像我为了清晰起见而上面所做的那样。
实际上,上面的代码可以写成:
typedef struct MyStruct
{
/* etc. */
} MyStruct ;
据我所知,这实际上是C++在幕后使用其更简单的结构声明来保持与C兼容的方式:
// C++ explicit declaration by the user
struct MyStruct
{
/* etc. */
} ;
// C++ standard then implicitly adds the following line
typedef MyStruct MyStruct;
回到C语言,我见过两种用法(分别使用不同的名称和相同的名称),我不知道有什么缺点,因此如果你不使用C单独的“命名空间”来区分结构体和其他符号,使用相同的名称可以使阅读更简单。
如果一个结构定义将要在多个源文件中使用,那么您应该将其放在头文件中。然后在需要使用该结构的任何源文件中包含该头文件。
extern
声明不用于结构定义,而是用于变量声明(即,您已定义了某个具有结构类型的数据值)。如果您想要在多个源文件中使用同一变量,请在头文件中声明为extern
:
extern struct a myAValue;
接下来,在一个源文件中定义实际变量:one
struct a myAValue;
如果您忘记执行此操作或者意外在两个源文件中定义了它,链接器会告诉您这一点。
GLOBAL
定义为extern
或空,然后将变量声明为GLOBAL struct a myAValue;
。在大多数源文件中,您可以安排使用#define GLOBAL extern
版本(_声明_变量),并且在恰好一个源文件中,它会导致使用空定义,从而_定义_变量。 - TripeHounda.h:
#ifndef A_H
#define A_H
struct a {
int i;
struct b {
int j;
}
};
#endif
好的,现在你只需要将a.h包含到想要使用这个结构体的文件中。
struct b
的右括号后面至少应该有一个分号,但是您的结构体a
声明了一个未使用的类型(您可能需要在内部右括号之后、分号之前定义一个成员名称,例如k
)。 - Jonathan Leffler