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

时间:2013-05-24 18:42:05

标签: c struct

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

本书说,“结构不能包含自身的实例。例如,struct employee的类型struct employee中的变量不能在struct employee2 { char firstName[ 20 ]; char lastName[ 20 ]; unsigned int age; struct employee2 *ePtr; }; 的定义中声明。但是,指向struct employee的指针,可能包括在内。“

然后给出以下示例:

struct employee

我不明白这是做什么的,如果没有2,我不理解对struct employee2 *ePtr的引用。

struct employee如何了解{{1}}或我是否在这里?

4 个答案:

答案 0 :(得分:9)

更有意义的例子可能是

struct employee2* manager;

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

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

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

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

typedef struct {
    int data;
    node* next;
} node;

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

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

答案 1 :(得分:3)

你不能把整个结构放在自身内部,因为它会无限递归。

但是你可以将struct的另一个实例的地址放在struct中;这是一个指针是什么......一个大小为SomeStruct*的地址总是相同的,所以编译器知道要为一个结构实例做多少内存。

答案 2 :(得分:3)

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

struct foo {

它知道会有一个带有标签foo的结构;此类型(struct foo)此刻尚未完成。只有在看到匹配的}之后才会完成。

然而,这是神奇的,指向不完整类型的指针是一个完整的类型,因为任何指针的大小都是已知的 - 无论它指向何种类型。所以在上面的三个标记之后,可以声明一个struct member

  struct foo *ptr_to_struct_foo;

struct foo内和匹配的}之前。

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

void foo;

但是,声明指向这种类型的指针是完全正常的:

void *foo;

但是,不允许通过ptr-to-void进行间接指导。为什么?现在你知道了答案:因为那会产生一种不完整的类型。

答案 3 :(得分:1)

这会导致大小无限大。想想结构:

struct my_struct {
  int x;
  struct my_struct y;
}

这将有一个大小:

sizeof(struct my_struct) >= sizeof(int) + sizeof(struct my_struct);

显然无法解决。

但是,指向结构的指针不会出现此问题。

struct my_struct2 {
  int x;
  struct my_struct2* y;
}

现在尺寸可以。

sizeof(struct my_struct2) >= sizeof(int) + sizeof(struct my_struct2*);

您应该了解

之间的区别
sizeof(struct my_struct2)
and
sizeof(struct my_struct2*)