具有正确标头的 C 结构定义问题

C struct definition problem with correct headers

提问人:jinTgreater 提问时间:11/6/2023 更新时间:11/6/2023 访问量:120

问:

请原谅我的啰嗦。

这就是我喜欢为在模块中声明用户函数而制作标头的方式。

struct Object;
void function( struct Object * , ... );

这只是为了让模块的用户不会有一个杂乱无章的头文件,其中包含结构中使用的所有内容。

使用具有结构定义的 .c 文件。让我们在这个主结构体中拥有结构体。

struct Object {
    int item;
    struct Component component;
};

让我们想在用户定义的结构中使用这个模块对象。说:

#include "module.h" /*declarations*/
...
struct UserItem {
    int something;
    ...
    struct Object object;
} userThing;

这是我的 C 预处理问题。

这会导致问题。编译过程中,struct Object 的大小尚未定义,因此无法定义 struct UserItem 的大小,编译失败error: field 'object' has incomplete type

现在有什么补救措施??显然,可以使用结构指针,但这增加了使用动态内存分配进行结构初始化的烦人步骤。为结构定义设置一个单独的标头怎么样?好的,但这意味着结构符号名称现在与这些名称混杂在一起,例如结构组件。此外,用户还必须包含此头文件以及主模块头文件。在我看来,这不是一个好的解决方案。甚至可能做一些类似的事情struct Object { uint8_t component_mem[SIZE]; };

我唯一的想法是在编译中有一个步骤,其中结构定义被全局预处理,以便找到所有大小。我相信这必须在链接阶段就已经完成,因为取消了对结构指针的引用?

如果我犯了错误,或者已经有一个很好的解决方案,请告诉我。

类似的 stackoverflow 页: 1

C 头文件

评论

0赞 user3386109 11/6/2023
“我认为这必须在链接阶段就已经完成”不,链接器对结构定义一无所知。
5赞 user3386109 11/6/2023
如果用户代码需要结构的实例,而不仅仅是指向结构的指针,那么最好将完整定义放在头文件中。ObjectObject
2赞 David C. Rankin 11/6/2023
是的,这是 - 出于您在问题中陈述的确切原因。那只是 C。唯一的选择是丑陋的笨拙,或者你基本上重新发明了轮子,试图为OOP语言编写基础抽象。两者都不能很好地利用你的时间。(教育除外)关于该方法的一个有趣的读物是 Object-Oriented Programming With ANSI-C 的第 2 章和第 3 章 一个接近的替代方案,但特定于程序 - 每次......另一个例子是 libpng 中的结构png
4赞 user3386109 11/6/2023
无法克服的问题是编译器不知道不完整类型的大小。这是 C 语言设计所固有的。所以你的选择是:1)接受它并继续你的生活,2)试着绕开它,或者3)发明你自己的语言。
2赞 BoP 11/6/2023
@jinTgreater - 如果你一直追溯到C语言,C的最初目标是允许Ken Thompson在更高级别的语言中实现UNIX。当时,没有必要隐瞒实现细节,因为所有细节都是他自己写的!后来,他们的一位同事选择了选项 3),并设计了一种结构可以具有和部分的语言。privatepublic

答:

6赞 chux - Reinstate Monica 11/6/2023 #1

隐藏信息是一个崇高的目标,但有时也是一种痛苦。

C 只是不支持 OP 的目标,通过公共文件知道 OP 的内部结构,但不使用它们。struct UserItem

我见过的最好的是警告
将完整定义移动到 .h 文件

// Object.h
/*
I know you may be tempted to access these struct members, but **DO NOT USE THEM**.  
They are only here for sizing purposes and zero initialization.
Only Object support function should access members.
*/

struct Component {
    int SecretDecoderRing;
    double magic_number;
    char psword[42];
};

struct Object {
    int item;
    struct Component component;
};

void Object_function1( struct Object * , ... );
void Object_function2( struct Object * , ... );

struct Component定义、定义和警告可以存在于 Object.h 包含的单独 Object_xxx.h 文件中,以实现适度的隐藏。然而,包括 Object.h 最终仍然会暴露这些细节。struct Objectstruct

评论

0赞 jinTgreater 11/6/2023
查看我的评论
0赞 chux - Reinstate Monica 11/6/2023
@jinTgreater不需要 .然而,如果你想允许而不是,注意*,那么你正在进行一个需要完整定义的设计 - 隐藏数据的唯一方法是与遵守警告的合作用户合作。struct Object; void function( struct Object * , ... );struct Objectstruct UserItem { int something; ... struct Object object; } userThing;struct UserItem { int something; ... struct *Object object; } userThing;struct Object
2赞 chux - Reinstate Monica 11/6/2023
@jinTgreater我尝试过固定大小的缓冲区等技巧,结果却回到了:信任用户,至少一点点。unionsstatic_asserts
0赞 chux - Reinstate Monica 11/6/2023
@jinTgreater 如果您不想信任该用户,请仅允许使用 .struct UserItem { int something; ... struct *Object object; } userThing;*