为什么结构不能拥有与自身类型相同的成员?

hax*_*ode 5 c struct

我一直在理解这个结构发生了什么(来自C for ProgrammersDeitel的书).

该书说:"结构不能包含自身的实例.例如,struct employee不能在定义中声明类型的变量struct employee.但是,可以包含指向struct employee的指针."

然后给出以下示例:

struct employee2 {
   char firstName[ 20 ];

   char lastName[ 20 ];

   unsigned int age;

   struct employee2 *ePtr;
};
Run Code Online (Sandbox Code Playgroud)

我不明白这是做什么的,我不明白struct employee没有2 的参考.

我怎么struct employee2 *ePtr知道struct employee或者我不在这里?

dje*_*lin 10

一个更有意义的例子可能是

struct employee2* manager;
Run Code Online (Sandbox Code Playgroud)

请注意,要删除这*意味着C编译器必须列出顶级员工所需的44个(左右)字节,然后是下一个内部员工的另外44个字节,然后是下一个内部员工的44个字节,然后是44个下一个下一个内部员工......等等.不用说这是编译错误.

此外,这种不可能的结构会迫使他们成为不同的员工,并且要求在创建任何员工时创建所有管理者,这些管理者必须不是空的,而且是不同的. 这意味着您不能拥有首席执行官,而NULL根据您的实施情况,首席执行官的经理可能是指针.如果不删除员工系统中的记录(即解雇员工)并重新创建(招聘),这也需要更改管理员,这也需要撤销建筑物访问,计算机访问等等.我的观点是,没有指针是一种非常非常糟糕的方式来模拟现实世界中正在发生的事情.

但是,C编译器可以为员工布置44个字节,然后为员工管理器的地址布置4个字节,如果它不为空,则将指向44 + 4个字节.请注意,这些不一定是不同的字节 - 也许员工是她自己的经理(你的业务逻辑应该禁止这个但是嘿,C关心什么).

较低级别的示例是链接列表,其更类似于:

typedef struct {
    int data;
    node* next;
} node;
Run Code Online (Sandbox Code Playgroud)

但同样的想法.除非您准备好一次创建所有无限不同的节点,否则这将无效.链接列表将以一个NULL值结束,该值可以用指针表示,但不能是一个不能为空的结构,因为它需要占用内存.

无论如何,指针是一种结构引用另一种结构的方式,而无需再次物理地布置存储器.C是一种低级语言,但是如果你从编译器的角度学习思考一些更高级别的概念就有意义了.例如,删除*这也意味着员工"拥有"她的经理.从现实世界的角度来看,这没有意义,从内存管理的角度来看也没有意义.(虽然,有些感觉父母可以拥有孩子......这不是一个完美的类比.)


Jen*_*ens 5

当您了解不完整类型的 C 概念时,这里的魔力就会变得清晰起来。结构只能包含完整的类型,即编译器知道其大小的类型。当编译器看到

struct foo {
Run Code Online (Sandbox Code Playgroud)

它知道会有一个带有 foo 标签的结构;这种类型 ( struct foo) 目前还不完整。}直到看到匹配时它才变得完整。

然而,这就是神奇之处,指向不完整类型的指针是完整类型,因为任何指针的大小都是已知的——无论它指向什么类型。所以在上面的三个标记之后,声明一个结构体成员就可以了

  struct foo *ptr_to_struct_foo;
Run Code Online (Sandbox Code Playgroud)

在 a 内struct foo和匹配之前}

另一种经常使用的不完整类型是void--这种类型甚至无法完成,这就是为什么 C 不允许你声明

void foo;
Run Code Online (Sandbox Code Playgroud)

然而,声明指向这种类型的指针是完全可以的:

void *foo;
Run Code Online (Sandbox Code Playgroud)

但是通过 ptr-to-void 间接进行当然是不允许的。为什么?现在您知道答案了:因为这会产生不完整的类型。