如果我有一个带结构的source.c文件:
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的指针声明函数,则不需要完整的struct定义.一个简单的前向声明,如:
struct a ;
足够了,它会减少耦合.
这是另一种方式,在某种程度上更容易,但模块化程度较低:某些只需要您的结构才能工作的代码仍然必须包含所有类型.
在C++中,这可能会导致有趣的复杂化,但这不是主题(没有C++标记),所以我不会详细说明.
我也许没有看到这一点,但Greg Hewgill在他的帖子中有一个非常好的答案如何在一个标题中声明一个结构,该结构将由c中的多个文件使用?.
如果您使用的是C++,请不要.
如果你使用C,你应该.
原因是C struct管理可能很麻烦:你必须在使用它的每个地方声明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正确地评论道.
Craig Barnes在评论中提醒我们,您不需要为struct"tag"名称及其"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单独的"名称空间",使用相同的名称会使阅读更简单.
对于要在多个源文件中使用的结构定义,您绝对应该将其放在头文件中.然后在任何需要该结构的源文件中包含该头文件.
的extern
声明不用于结构定义,而是被用于变量声明(即,具有结构式的一些数据值已定义).如果要在多个源文件中使用相同的变量,请将其声明为extern
头文件,如:
extern struct a myAValue;
然后,在一个源文件中,定义实际变量:
struct a myAValue;
如果您忘记执行此操作或意外地在两个源文件中定义它,链接器将通知您.
啊:
#ifndef A_H #define A_H struct a { int i; struct b { int j; } }; #endif
你去,现在你只需要将ah包含在你想要使用这个结构的文件中.