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