简体   繁体   English

C向前声明查询

[英]C forward declaration query

I have a situation where two of my header files require the data structures defined in either one, ie no matter which order you include them it won't compile 我遇到这样一种情况,其中我的两个头文件都需要其中一个定义的数据结构,即无论您以何种顺序包含它们,都不会编译

however, one of the problem data structures only contains pointers to the data structure declared in the other header file so I would have though that technically it doesn't need to know at this point how big the data structure is so it shouldn't be complaining 但是,一个有问题的数据结构仅包含指向另一个头文件中声明的数据结构的指针 ,因此尽管从技术上讲我现在不需要知道该数据结构有多大,所以不应抱怨

A simplified example of what I mean is outlined below. 下面概述了我的意思的简化示例。 I would have thought that the array of modes in Library doesn't need to know how big a Mode is, only how big a pointer to a Mode is therefore the compiler shouldn't complain if it hasn't yet seen the declaration of Mode in the other header file. 我本以为Library中的模式数组不需要知道Mode有多大,只需知道指向Mode的指针有多大,因此,如果编译器尚未看到Mode的声明,就不必抱怨在另一个头文件中。

header_1.h

typedef struct
{
    Mode **modes; 
} Library;

header_2.h

typedef struct
{
    int number;
    char *name;
} Mode;

It doesn't need to know the size, but it must have seen a declaration. 它不需要知道大小,但是必须已经看到一个声明。 A forward declaration 前瞻性声明

typedef struct Mode Mode;

before the definition of struct Library suffices. 在定义struct Library就足够了。

As currently written, your example does not show the mutual cross-referencing that you mention in the question. 就目前而言,您的示例并未显示您在问题中提到的相互交叉引用。

The compiler must be told something about each type it uses. 必须告知编译器有关其使用的每种类型的信息。 You could use in header_1.h just: 您可以在header_1.h使用:

typedef struct Mode Mode;

typedef struct
{
    Mode **modes; 
} Library;

That would make it compile, at least. 至少可以编译。 The compiler doesn't need the details, but it does need to know that Modes is a type. 编译器不需要详细信息,但确实需要知道Modes是一种类型。

Edit: Note that header_2.h should be modified for this to work. 编辑:请注意,应该修改header_2.h才能使其正常工作。 You have to ensure that each typedef appears just once. 您必须确保每个typedef仅出现一次。 After you have the typedefs in place, you specify the structure content (definition) once, and you omit the keyword typedef and the typedef name from the structure definition. 放置好typedef后,只需指定一次结构内容(定义),然后在结构定义中省略关键字typedef和typedef名称。 And you have to decide on exactly the cross-references will be managed. 而且您必须确定将要正确管理交叉引用。 For example, should header_1.h include header_2.h anyway. 例如, header_1.h应该header_1.h包含header_2.h

I don't remember encountering a case where I really needed mutually referencing structures (in quite a long time programming — long enough that I could have forgotten a example). 我不记得遇到过真正需要相互引用结构的情况(在很长时间的编程中-足够长的时间,我可能会忘记一个示例)。 I do now remember a case of structures mutually referencing each other; 我现在确实记得一个结构相互引用的情况。 it was in a version of make originally written for Minix. 它是最初为Minix编写的make版本。 I still regard such a requirement as somewhat 'pathological' (or, if you prefer, as a 'code smell') and as something to be avoided whenever possible. 我仍然认为这样的要求有些“病态”(或者,如果您愿意,则是“代码异味”),并且在任何可能的情况下都应避免。 If you really must manage it, then the section below explains how I'd go about doing it (and more or less how the make program did go about it). 如果您真的必须管理它,那么下面的部分将说明我将如何执行它(以及或多或少地使用make程序来实现它)。

Mutually-referencing structures 相互参照结构

If you truly have two mutually referencing structures, you should (re)consider why you think two headers are better than one. 如果确实有两个相互引用的结构,则应该(重新)考虑为什么您认为两个标头比一个更好。 If you still need two headers, you use an idiom like: 如果仍然需要两个标头,请使用如下习惯用法:

header_1.h 标头_1.h

#ifndef HEADER_1_H_INCLUDED
#define HEADER_1_H_INCLUDED

#ifndef TYPEDEF_MODE
#define TYPEDEF_MODE
typedef struct Mode Mode;
#endif
#ifndef TYPEDEF_LIBRARY
#define TYPEDEF_LIBRARY
typedef struct Library Library;
#endif

struct Library
{
    ...
    Mode    **modes;
    ...
};

#endif /* HEADER_1_H_INCLUDED */

header_2.h 标头_2.h

#ifndef HEADER_2_H_INCLUDED
#define HEADER_2_H_INCLUDED

#ifndef TYPEDEF_MODE
#define TYPEDEF_MODE
typedef struct Mode Mode;
#endif
#ifndef TYPEDEF_LIBRARY
#define TYPEDEF_LIBRARY
typedef struct Library Library;
#endif

struct Mode
{
    ...
    Library    **liblist;
    ...
};

#endif /* HEADER_2_H_INCLUDED */

The repeated typedef 'detection' code is not nice; 重复的typedef '检测'代码不是很好; a single header is better, in my estimation. 我估计单个标头会更好。 However, you can include header_1.h and header_2.h above in either order and it should compile. 但是,您可以按任意顺序在上面包含header_1.hheader_2.h ,并且应该进行编译。

I believe this is happening because "Mode" is a type defined using typedef and its not the name of the struct. 我相信这是因为“模式”是使用typedef定义的类型,而不是结构的名称。 You will either need to explicitly forward declare it or you can try using the code structured as follows: 您将需要明确地向前声明它,或者可以尝试使用如下结构的代码:

header_1.h

typedef struct
{
    struct _Mode_t **modes; 
} Library;

header_2.h

typedef struct _Mode_t
{
    int number;
    char *name;
} Mode;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM