递归结构的大小是多少?

时间:2013-11-01 05:49:54

标签: c

struct thing { 
    int x;
    thing* next;
} 

显然,大小是sizeof(int)+sizeof(thing*),但是sizeof(thing*)是什么?好吧,它是指向一个结构的指针的大小,该结构包含一个int加上指向另一个结构的指针的大小,该结构包含一个int和一个指向另一个结构的指针,该结构的大小为....... .........

所以我觉得事物的大小必须是无限的。 (当数学专业的学生拿起一本编程书时会发生这种情况。他把所有东西都带到了它的逻辑极端而感到困惑。)

4 个答案:

答案 0 :(得分:2)

结构尺寸

请注意,您引用的thing *struct thing 100%无关。这是C;你的标签是这样说的。您可以编写此代码以使代码编译干净:

typedef struct thing thing;
struct thing
{
    int    x;
    thing *next;
};

struct thing的最小尺寸为sizeof(int) + sizeof(thing *),但结构可能大于sizeof(int)。实际上,在我的(64位)机器上,结构的大小为16字节,即使int只是4.这是因为地址必须是8字节对齐,所以{之间有4个字节的填充{1}}和指针。

8字节对齐

  

你能解释一下“8字节对齐”是什么意思吗?

许多CPU要求N字节基本类型应存储在N的倍数地址。因此,1字节char变量可以存储在任何地址,但是2字节{ {1}}变量必须存储在2的倍数地址,4字节short变量必须存储在4的倍数地址等。对于某些机器,尤其是RISC架构,如果你试图读取错误的对齐,你会得到一个SIGBUS信号(和核心转储)。对于其他人来说,你最终会让CPU进行多次读取和钻头纠缠以获得正确的结果,但比数据正确对齐要慢得多。编译器知道这些都很昂贵,并确保它们不违反规则。并且编译器在必要时将结构填充到结构中,除了结构的开头,以确保结构中的元素正确对齐,并且结构类型的数组元素将正确对齐。

考虑一个64位编译器和数据结构:

int

即使单个struct list { struct list *next; int data; }; 可能只有12个字节(指针为8个字节,数据为4个字节),编译器会在末尾添加4个字节的填充,这样如果你有一个数组这些结构,数组中第二项的起始地址将在8个字节的倍数上正确对齐(需要因为地址是64位,8字节数量)。

无限大小

  

显然,sizeof(int)+ sizeof(thing *),但sizeof(thing *)是什么?好吧,它是一个指向结构的指针的大小,该结构包含一个int加上指向另一个结构的指针的大小,该结构包含一个int和一个指向另一个结构的指针,该结构的大小为........... .....

     

所以我想事情的大小必须是无限的。

这里没有无限的退步。结构的大小和指向结构的指针的大小是两个非常不同的东西。 C不允许递归类型:

struct list

这需要无限量的内存,甚至虚拟内存都无法模拟(计算机主内存中没有足够的位来保存无限大的数据结构的大小,更不用说无限大的结构本身了)。

但问题中的结构不包含结构;它包含一个指向结构的指针。 C标准保证结构的所有地址都是相同的大小(POSIX提出了更严格的要求 - 所有指向所有对象的指针和指向函数的指针必须具有相同的大小)。因此,指向结构的指针的大小是固定的 - 对于32位编译为4个字节,对于64位编译为8个字节(实际上,即使理论上可能存在例外)。并且结构的大小是固定且有限的。

答案 1 :(得分:1)

不,不,不,sizeof(struct thing*)只是指向结构所需指针的大小,可能在结构中的任何东西。 (例如,考虑空指针的情况。)

答案 2 :(得分:1)

不,指针的大小固定。所以thing的大小是sizeof(int)+ sizeof(指针)。

Nitpicker的角落:

通常遇到的CPU架构中指针的大小为4或8个字节,具体取决于CPU架构。

然而,一些不常见的架构(DSP芯片,奇怪的微控制器,PDP-10和其他面向字的架构)具有不同大小的指针。

此外,在一些不常见的体系结构中,指向不同大小的对象的指针本身具有不同的大小,因此,例如,sizeof(char *)!= sizeof(int *)。

此外,某些体系结构允许面向位的寻址,因此可以获取位域的地址,这通常是不允许的。 (C标准不允许这样做,但可以作为供应商扩展来完成。)

答案 3 :(得分:1)

指针的大小不依赖于指针的指针。指针将是一个单词的大小,因此系统可以是4或8个字节。