如何在c中的多个文件使用的头中声明一个结构



如果我有一个带有结构的源.c文件:

struct a { 
    int i;
    struct b {
        int j;
    }
};

如何在另一个文件(即func.c)中使用此结构体?

我应该创建一个新的头文件,在那里声明结构并将该头包含在func.c中吗?

还是应该在头文件中定义整个结构,并将其包含在source.cfunc.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包含到要使用此结构的文件中。

相关内容

  • 没有找到相关文章

最新更新