简体   繁体   English

Pure C: when using typdef void StructName in header file, the header file can't be included into the.c file

[英]Pure C: when using typdef void StructName in header file, the header file can't be included into the .c file

I have a header file that looks like this:我有一个看起来像这样的 header 文件:

typedef void Square;

extern Square*  Square_Init       (int width, int height);
extern void     Square_Delete     (Cube* cube);
extern int      Square_GetWidth   (Cube* cube);
extern int      Square_GetHeight  (Cube* cube);

and a.c file, looking something like this:和 a.c 文件,看起来像这样:

/* #include "square.h" */ /* compiler gets mad for redefining Square */

typedef struct {
    unsigned int width;
    unsigned int height;
} Square;

Square* Square_Init (int width, int height) {. . .}

void Square_Delete (Cube* cube) {. . .}

int Square_GetWidth (Cube* cube)  {. . .}

int Square_GetHeight (Cube* cube) {. . .}

When I finally include my header file in let's say main.c, all the functions work well.当我最终将我的 header 文件包含在 main.c 中时,所有功能都运行良好。 It is just a bit odd for me, that I can't include the square.h file into the square.c file.对我来说有点奇怪,我不能将 square.h 文件包含到 square.c 文件中。 Can it be done somehow?可以以某种方式完成吗?

What you seem to want to do is an opaque type.您似乎想要做的是不透明的类型。 But void * is not a type compatible with struct pointers, so you cannot use them interchangeably, and most definitely cannot use void interchangeably with a structure type.但是void *不是与结构指针兼容的类型,因此您不能互换使用它们,并且绝对不能将void与结构类型互换使用。


The correct way is to use a tagged structure without definition in the header, for example:正确的做法是使用header中没有定义的标记结构,例如:

typedef struct square Square;

and if you include the header in your .c file, you just need to add:如果您在.c文件中包含 header ,则只需添加:

struct square {
    unsigned int width;
    unsigned int height;
};

This code...这段代码...

 typedef void Square;

... is ok in itself. ... 本身没问题。 It declares the identifier Square to be an alias for the type void .它将标识符Square声明为void类型的别名。

This code...这段代码...

 typedef struct { unsigned int width; unsigned int height; } Square;

... is also ok by itself. ...本身也可以。 It declares the identifier Square to be an alias for a tagless structure type with members { unsigned int width; unsigned int height; }它将标识符Square声明为具有成员{ unsigned int width; unsigned int height; }的无标记结构类型的别名。 { unsigned int width; unsigned int height; } { unsigned int width; unsigned int height; } . { unsigned int width; unsigned int height; }

But the two are not at all compatible with each other.但两者完全不兼容。 Therefore, if you include the header into a C source file that includes the latter typedef then you have two conflicting declarations of the same typedef identifier.因此,如果您将 header 包含到包含后者 typedef 的 C 源文件中,那么您有两个相同typedef标识符的冲突声明。 Not only is the resulting behavior undefined, but this is one of the cases that a conforming C compiler is required to diagnose.不仅结果行为未定义,而且这是需要符合标准的 C 编译器进行诊断的情况之一。

Furthermore, although this declaration...此外,虽然这个声明...

 extern Square* Square_Init (int width, int height);

... is valid with either typedef , it has slightly different meaning depending on which is in scope where it appears. ... 对任何一个typedef都有效,它的含义略有不同,具体取决于它出现在 scope 中的哪个位置。 As a result, code that calls the function with the declaration from the header in scope has undefined behavior (but this is not a case that the compiler is required to diagnose).因此,使用 scope 中 header 的声明调用 function 的代码具有未定义的行为(但这不是编译器需要诊断的情况)。

Do not be confused by the fact that C provides automatic conversions back and forth between void * and other object pointer types.不要被 C 提供void *和其他 object 指针类型之间的自动来回转换这一事实混淆。 That's a matter of values being somewhat interchangeable, but it does not mean that the types are interchangeable.这是可以互换的问题,但这并不意味着类型可以互换。

Nevertheless, inasmuch as it is common in modern C implementations for pointers to different kinds of objects all to have the same size and representation, it is not so surprising that the undefined behavior arising from calling the function with a mismatched declaration in scope happens to manifest (so far) as exactly the behavior you expected. Nevertheless, inasmuch as it is common in modern C implementations for pointers to different kinds of objects all to have the same size and representation, it is not so surprising that the undefined behavior arising from calling the function with a mismatched declaration in scope happens to manifest (到目前为止)完全符合您的预期。 But that doesn't mean you should do this.但这并不意味着你应该这样做。

The easiest thing to do would be to move the latter typedef to the header, so that everyone agrees completely about what a Square is.最简单的做法是将后一个typedef移动到 header,这样每个人都完全同意Square是什么。 However, if you want to hide the definition of Square while allowing other code to use pointers to instances of that type and maintaining substantial type safety, then the header can forward declare Square as a structure type without (ever) defining the members, as Antti demonstrates in his answer .但是,如果您想隐藏Square的定义,同时允许其他代码使用指向该类型实例的指针并保持实质性的类型安全,那么 header 可以将Square转发声明为结构类型,而无需(永远)定义成员,如 Antti在他的回答中表明。 This makes Square an "opaque type" from the perspective of code that has only the declaration from the header.从只有 header 声明的代码的角度来看,这使得Square成为“不透明类型”。

暂无
暂无

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

相关问题 包含的 header 文件是否在 C 文件中展开 - Does the included header file expand in the C file 为什么在我的C头文件中包含freetype头文件会产生错误,但可以包含在.c文件中? - Why does including the freetype header files in my C header file produce an error, but can be included in the .c file? C文件包含的所有头文件的列表 - list of all header files included by a C file C Header 文件包含在另一个 header 文件中,并且两者都包含在 Z4A8A08F09D337B737B588344 文件中 - C Header file being included in another header file and both included in a c file 是目标文件(.o)中包含的.c文件中的头文件路径引用 - is header file path reference in .c file included in object file (.o) 如何在纯C和CUDA C文件中包含头文件? - How to include header file across pure C and CUDA C files? 在ac头文件中使用define - Using define in a c header file 在 C 或 C++ 中,如何防止 header 文件中先前的#define 影响另一个 Z099FB9953406FC 文件包含的 EEFC 文件? - in C or C++, how can I prevent previous #define in a header file from affecting another header file later included? 您可以将头文件包含到另一个头文件中,但是当在.c 文件中包含第二个头文件时,不会自动包含第一个头文件吗? - Can you include header file into another header file but when including the second header file in .c file, not automatically include the first one? C头文件格式 - C header file format
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM