C语言的Forward Struct声明;不工作

时间:2021-05-04 15:05:29

I read all the other posts with no success yet (eg forward declaration of a struct in C?)

我阅读了所有其他没有成功的帖子(如在C语言中转发了一个struct)

There are two header files with functions which reference structs from each others' headers. Forward declaration isn't working...surely because i'm still doing it incorrectly:) Thoughts?

有两个带有函数的头文件,它们从彼此的头文件中引用结构。前置声明不工作…当然,因为我还在做错误的事情:)思想?

foo.h:

foo。:

typedef struct{
...
}foostruct;
extern foostruct fooStruct; //this struct used in foo.c and other c files
typedef struct barstruct; //attempt at forward declaration
void fooFctn(barstruct *barVar); //needs definition from bar.h

bar.h:

bar.h:

typedef struct{
...
}barstruct;
extern barstruct barStruct; //this struct used in bar.c and other c files
typedef struct foostruct; //attempt at forward declaration
void fooFctn(foostruct *fooVar); //needs definition from foo.h

The error is

错误的是

error: useless storage class specifier in empty declaration [-Werror]
src/search.h:123:18: error: unknown type name 'foostruct'

Since these structs were typedef-d originally i also tried just "foostruct;" without the identifier which (of course) doesn't work, likewise declaring "typedef struct fooVar foostruct" generates a redefinition error.

由于这些结构是typedef-d,所以我也尝试了“foostruct”,没有标识符(当然)不工作,同样声明“typedef struct fooVar foostruct”会生成一个重新定义错误。

3 个解决方案

#1


4  

In your foo.h, this code:

在你的foo。h,这段代码:

typedef struct barstruct;

is a degenerate typedef that announces that struct barstruct exists, but does not give an alternative name for it (hence the 'useless storage class specifier in empty declaration' warning/error). You need:

是一个degenerate typedef,它声明了struct barstruct的存在,但是没有给它提供一个替代名称(因此,在“空的声明”警告/错误中,“无用的存储类说明符”)。你需要:

typedef struct barstruct barstruct;

Then the code will work properly in foo.h. The corresponding change is needed in bar.h for struct foostruct.

然后代码将在foo.h中正常工作。在bar中需要相应的更改。为struct foostruct h。

However, that still leaves you with a problem. The type barstruct declared in foo.h is not identical to the type barstruct declared in bar.h (because one is a tagged structure and one is a tagless structure). There are several ways around this. In C11 (but not C99 or C89), you can repeat a typedef if they're identical.

但是,这仍然会给您带来一个问题。在foo中声明的类型barstruct。h与bar中声明的类型barstruct不相同。h(因为一个是标记结构,一个是无标记结构)。有很多方法可以解决这个问题。在C11(但不是C99或C89)中,如果它们是相同的,则可以重复typedef。

You would therefore have the two typedef lines:

因此,您将拥有两个typedef行:

typedef struct barstruct barstruct;
typedef struct foostruct foostruct;

at the top of the headers, and then define in bar.h:

在标题的顶部,然后在bar.h中定义:

struct barstruct { … };

and in foo.h:

在foo。:

struct foostruct { … };

If compatibility with earlier versions of C is important, then you need to consider using struct barstruct and struct foostruct in the function declarations:

如果与早期版本C的兼容性很重要,那么您需要考虑在函数声明中使用struct barstruct和struct foostruct:

foo.h

typedef struct foostruct foostruct;

struct foostruct
{
   …
};

extern foostruct fooStruct;
struct barstruct;
void fooFctn(struct barstruct *barVar);

and analogously for bar.h. This will also work with C11, of course.

并为bar.h类似地。当然,这也适用于C11。

#2


2  

Properly typedef your struct should resolve your problem.

正确的typedef你的结构应该解决你的问题。

typedef struct foostruct foostruct;

#3


1  

Structures and tags

结构和标记

struct { ... }; is an anonymous structure. It is only useful with typedefs, and only when that typedef name is used and declared in that one file. In other words, it cannot be used with forward declarations.

结构体{…};是一个匿名的结构。它只在typedef中有用,并且只有在使用该typedef名称并在该文件中声明时才有用。换句话说,它不能用于正向声明。

However, struct X { ... }; is a structure of type struct X. It can be used for forward declarations. Note that X is just the tag name used to denote a specific structure type, not the actual type. The tag name is used to distinguish between other declared structure types. This confuses people sometimes, so an example might help. Note that all of the declared structure types are different:

然而,结构X{…};是一种结构类型的结构,它可以用于转发声明。注意,X只是用来表示特定结构类型的标记名,而不是实际类型。标记名称用于区分其他声明的结构类型。这有时会让人困惑,所以一个例子可能会有帮助。请注意,所有声明的结构类型都是不同的:

/* Declare an anonymous structure. */
struct {
    int n;
};

/* Another anonymous structure. It in different from the previous one. */
struct {
    double d;
};

/* Declare a structure of type `struct bar'. */
struct bar {
    int n;
};

/* Declare a structure of type `struct foo'. */
struct foo {
    int n;
};


/* Declare a variable `var' of type `struct foo'. */
struct foo var;

/* Unless a typedef for the `foo' type exists, or a preprocessor macro is used to replace `foo' with an actual type, this is a compilation error. */
foo var2;

Note that if you attempt to declare two structures with the same tag name, it is an error.

注意,如果您试图声明两个具有相同标记名称的结构,那么它就是一个错误。

typedefs

typedef

The form for a typedef is the same as for a variable declaration with no initializer:

typedef的形式与没有初始化器的变量声明相同:

typedef TYPE NAME;

For example:

例如:

typedef int Integer;

declares the Integer type to be the same as int. The same can be done with structures:

声明整数类型与int类型相同。

/* Typedef'd anonymous structure */
typedef struct {
    int foo;
} fooBType;

/* Typedef'd `struct foostruct' structure */
typedef struct foostruct {
    int foo;
} fooGType;

The difference between the two:

两者之间的区别:

  • forward declarations of the structure type referenced by fooBType in other files are not possible because the structure referenced by fooBType is anonymous
  • 由于fooBType引用的结构是匿名的,所以在其他文件中引用的结构类型的forward声明是不可能的。
  • forward declarations of the structure type struct foostruct referenced by fooGType are possible because the type is able to be referenced by the structure tag and the struct keyword, as in struct foostruct or typedef struct foostruct fooGType;
  • 由于类型可以被结构标记和struct关键字所引用,因此可以引用fooGType引用的结构类型结构体的前向声明,就像struct foostruct或typedef struct foostruct fooGType一样;

I hope this helps.

我希望这可以帮助。

#1


4  

In your foo.h, this code:

在你的foo。h,这段代码:

typedef struct barstruct;

is a degenerate typedef that announces that struct barstruct exists, but does not give an alternative name for it (hence the 'useless storage class specifier in empty declaration' warning/error). You need:

是一个degenerate typedef,它声明了struct barstruct的存在,但是没有给它提供一个替代名称(因此,在“空的声明”警告/错误中,“无用的存储类说明符”)。你需要:

typedef struct barstruct barstruct;

Then the code will work properly in foo.h. The corresponding change is needed in bar.h for struct foostruct.

然后代码将在foo.h中正常工作。在bar中需要相应的更改。为struct foostruct h。

However, that still leaves you with a problem. The type barstruct declared in foo.h is not identical to the type barstruct declared in bar.h (because one is a tagged structure and one is a tagless structure). There are several ways around this. In C11 (but not C99 or C89), you can repeat a typedef if they're identical.

但是,这仍然会给您带来一个问题。在foo中声明的类型barstruct。h与bar中声明的类型barstruct不相同。h(因为一个是标记结构,一个是无标记结构)。有很多方法可以解决这个问题。在C11(但不是C99或C89)中,如果它们是相同的,则可以重复typedef。

You would therefore have the two typedef lines:

因此,您将拥有两个typedef行:

typedef struct barstruct barstruct;
typedef struct foostruct foostruct;

at the top of the headers, and then define in bar.h:

在标题的顶部,然后在bar.h中定义:

struct barstruct { … };

and in foo.h:

在foo。:

struct foostruct { … };

If compatibility with earlier versions of C is important, then you need to consider using struct barstruct and struct foostruct in the function declarations:

如果与早期版本C的兼容性很重要,那么您需要考虑在函数声明中使用struct barstruct和struct foostruct:

foo.h

typedef struct foostruct foostruct;

struct foostruct
{
   …
};

extern foostruct fooStruct;
struct barstruct;
void fooFctn(struct barstruct *barVar);

and analogously for bar.h. This will also work with C11, of course.

并为bar.h类似地。当然,这也适用于C11。

#2


2  

Properly typedef your struct should resolve your problem.

正确的typedef你的结构应该解决你的问题。

typedef struct foostruct foostruct;

#3


1  

Structures and tags

结构和标记

struct { ... }; is an anonymous structure. It is only useful with typedefs, and only when that typedef name is used and declared in that one file. In other words, it cannot be used with forward declarations.

结构体{…};是一个匿名的结构。它只在typedef中有用,并且只有在使用该typedef名称并在该文件中声明时才有用。换句话说,它不能用于正向声明。

However, struct X { ... }; is a structure of type struct X. It can be used for forward declarations. Note that X is just the tag name used to denote a specific structure type, not the actual type. The tag name is used to distinguish between other declared structure types. This confuses people sometimes, so an example might help. Note that all of the declared structure types are different:

然而,结构X{…};是一种结构类型的结构,它可以用于转发声明。注意,X只是用来表示特定结构类型的标记名,而不是实际类型。标记名称用于区分其他声明的结构类型。这有时会让人困惑,所以一个例子可能会有帮助。请注意,所有声明的结构类型都是不同的:

/* Declare an anonymous structure. */
struct {
    int n;
};

/* Another anonymous structure. It in different from the previous one. */
struct {
    double d;
};

/* Declare a structure of type `struct bar'. */
struct bar {
    int n;
};

/* Declare a structure of type `struct foo'. */
struct foo {
    int n;
};


/* Declare a variable `var' of type `struct foo'. */
struct foo var;

/* Unless a typedef for the `foo' type exists, or a preprocessor macro is used to replace `foo' with an actual type, this is a compilation error. */
foo var2;

Note that if you attempt to declare two structures with the same tag name, it is an error.

注意,如果您试图声明两个具有相同标记名称的结构,那么它就是一个错误。

typedefs

typedef

The form for a typedef is the same as for a variable declaration with no initializer:

typedef的形式与没有初始化器的变量声明相同:

typedef TYPE NAME;

For example:

例如:

typedef int Integer;

declares the Integer type to be the same as int. The same can be done with structures:

声明整数类型与int类型相同。

/* Typedef'd anonymous structure */
typedef struct {
    int foo;
} fooBType;

/* Typedef'd `struct foostruct' structure */
typedef struct foostruct {
    int foo;
} fooGType;

The difference between the two:

两者之间的区别:

  • forward declarations of the structure type referenced by fooBType in other files are not possible because the structure referenced by fooBType is anonymous
  • 由于fooBType引用的结构是匿名的,所以在其他文件中引用的结构类型的forward声明是不可能的。
  • forward declarations of the structure type struct foostruct referenced by fooGType are possible because the type is able to be referenced by the structure tag and the struct keyword, as in struct foostruct or typedef struct foostruct fooGType;
  • 由于类型可以被结构标记和struct关键字所引用,因此可以引用fooGType引用的结构类型结构体的前向声明,就像struct foostruct或typedef struct foostruct fooGType一样;

I hope this helps.

我希望这可以帮助。