结构尺寸
请注意,thing *
您所指的 100% 与 无关struct thing
。这是C;你的标签是这样说的。你可以这样写来使代码编译干净:
typedef struct thing thing;
struct thing
{
int x;
thing *next;
};
的最小尺寸struct thing
是sizeof(int) + sizeof(thing *)
,但结构可以比这更大。实际上,在我的(64 位)机器上,结构的大小为 16 字节,尽管只有 4 个字节。这是因为地址必须是 8 字节对齐的,所以在和指针sizeof(int)
之间有 4 个字节的填充。int
8字节对齐
你能解释一下“8字节对齐”是什么意思吗?
许多 CPU 要求 N 字节基本类型应存储在 N 的倍数的地址中。因此,1 字节char
变量可以存储在任何地址,但 2 字节short
变量必须存储在2的倍数,4字节int
变量必须存储在 4 的倍数的地址中,等等。对于某些机器,尤其是 RISC 架构,如果您尝试读取错误的对齐方式,则会收到 SIGBUS 信号(和核心转储)。对于其他人,您最终会让 CPU 进行多次读取和位旋转以获得正确的结果,但比数据正确对齐时要慢得多。编译器知道这些很昂贵,并确保它们不会违反规则。并且编译器在必要时在结构中引入填充,除了结构的开头之外的任何地方,以确保结构中的元素正确对齐,并且结构类型数组的元素将正确对齐。
考虑一个 64 位编译器和数据结构:
struct list
{
struct list *next;
int data;
};
即使单个struct list
可能只有 12 个字节(8 个字节用于指针,4 个字节用于数据),编译器将在末尾添加 4 个字节的填充,这样如果您有这些结构的数组,则数组中的第二项将在 8 字节的倍数上正确对齐(需要,因为地址是 64 位,8 字节数量)。
无限大小
大小显然是 sizeof(int)+sizeof(thing*),但是 sizeof(thing*) 是什么???嗯,它是指向包含 int 的结构的指针的大小加上指向另一个包含 int 的结构的指针的大小和指向另一个结构的指针的大小,该结构的大小为...... ......
所以我猜事物的大小一定是无限的。
这里没有无限的倒退。结构的大小和指向结构的指针的大小是两个非常不同的东西。C 不允许递归类型:
struct xyz { int data; struct xyz nested; }; /* Invalid C and C++ and ... */
这将需要无限量的内存,甚至虚拟内存也无法模拟(计算机的主内存中没有足够的位来容纳无限大的数据结构的大小,更不用说无限大的结构本身了)。
但是问题中的结构不包含结构;它包含一个指向结构的指针。C 标准保证结构的所有地址大小相同(POSIX 提出了更严格的要求——指向所有对象的所有指针和指向函数的指针必须大小相同)。所以指向结构的指针的大小是固定的——32 位编译为 4 个字节,64 位编译为 8 个字节(实际上,即使理论上可能存在异常)。并且结构的大小是固定的和有限的。