C和H文件中的Typedef和Struct

Lei*_*sen 7 c struct typedef include

我一直在使用以下代码来创建各种结构,但只给C文件外的人一个指向它的指针.(是的,我知道他们可能会搞乱它,所以它不完全像Java中的私有关键字,但对我来说没关系).

无论如何,我一直在使用以下代码,今天我看了它,我真的很惊讶它实际上正在工作,任何人都可以解释为什么这是?

在我的C文件中,我创建了我的结构,但是不要在typedef命名空间中给它一个标记:

struct LABall {
    int x;
    int y;
    int radius;
    Vector velocity;
};
Run Code Online (Sandbox Code Playgroud)

在H文件中,我把它放在:

typedef struct LABall* LABall;
Run Code Online (Sandbox Code Playgroud)

我显然在c文件中使用#include"LABall.h",但我没有在头文件中使用#include"LABall.c",因为这会破坏单独头文件的整个目的.那么,为什么我还没有实际包含H文件中的LABall*结构的指针呢?是否与跨文件的struct命名空间有关,即使一个文件没有链接到另一个文件?

谢谢.

ndi*_*dim 23

像这样的东西的标准模式是有一个foo.h定义API 的文件

typedef struct _Foo Foo;

Foo *foo_new();
void foo_do_something(Foo *foo);
Run Code Online (Sandbox Code Playgroud)

以及foo.c为该API提供实现的文件

struct _Foo {
   int bar;
};

Foo *foo_new() {
    Foo *foo = malloc(sizeof(Foo));
    foo->bar = 0;
    return foo;
}

void foo_do_something(Foo *foo) {
    foo->bar++;
}
Run Code Online (Sandbox Code Playgroud)

这将隐藏所有的内存布局,并在实施该结构的大小foo.c,并通过公开的接口foo.h是完全独立的内部组成:caller.c它不仅#include "foo.h"将只需要存储一个指针的东西,和指针总是相同的尺寸:

#include "foo.h"

void bleh() {
    Foo *f = foo_new();
    foo_do_something(f);
}
Run Code Online (Sandbox Code Playgroud)

注意:我已将释放内存作为练习释放给读者.:-)

当然,这意味着下面的文件broken.c工作:

#include "foo.h"

void broken() {
    Foo f;
    foo_do_something(&f);
}
Run Code Online (Sandbox Code Playgroud)

因为Foo在此文件中不知道实际创建类型变量所需的内存大小.


rz0*_*rz0 7

既然你问这个语言"为什么"的确切原因,我假设你需要一些精确的参考.如果你发现那个学究,只需跳过笔记......

它的作用是因为两件事:

  • 所有指向结构类型的指针都具有相同的表示形式(请注意,就标准C而言,并非所有指针类型都是如此).[1] 因此,编译器有足够的信息来为指针到结构类型的所有用法生成适当的代码.

  • 标签名称空间(struct,enum,union)确实与所有翻译单元兼容.[2] 因此,这两个结构(即使一个未完全定义,即它缺少成员声明)是同一个.

(顺便说一句,#import是非标准的.)

[1]根据n1256§6.2.5.27:

所有指向结构类型的指针都应具有相同的表示和对齐要求.指向其他类型的指针不需要具有相同的表示或对齐要求.

[2]根据n1256§6.2.7.1:

如果它们的标记和成员满足以下要求,则在单独的转换单元中声明的两个结构,联合或枚举类型是兼容的:如果使用标记声明一个,则另一个应使用相同的标记声明.如果两者都是完整类型,则适用以下附加要求:[与我们无关].