structof struct in struct

时间:2016-07-12 13:57:29

标签: c struct

struct S1
{
    char c;
    int i;
};

struct S3
{
    char c1;
    struct S1 s;
    double c2;
};

我正在尝试计算sizeof(S3),从我的程序中它是24.我不知道的是结构S1在S3内的偏移量,这个偏移是否有任何规则?我认为“S1的偏移必须是其自身大小的N倍,即N * sizeof(S1)”,然而,我发现它不是真的。谢谢你的帮助。

4 个答案:

答案 0 :(得分:4)

$scope.clickListener = function () { document.addEventListener("click", function myListener(event) { console.log(event.target); console.log(arguments.callee.name) }, false); }; 标准在这方面有意灵活。

它保证的是(i)C中第一个元素的地址与struct的地址相同,以及(ii)数据成员按照它们的顺序出现在struct中声明。 (iii)空struct将具有非零struct。最后一个意味着指针算术在空结构上有效。

特别是, padding (任意数量)允许插入任何结构成员之间,最后。

答案 1 :(得分:1)

正如Bathsheba所说,编译器填充结构的方式不受标准规定。也就是说,这是最有可能发生的事情。

需要对齐特定类型的变量,使其地址是该类型大小的倍数。因此,2字节变量需要从2字节地址开始,4字节变量从4字节地址开始,等等。对于struct,对齐是最大的" base"类型。对于数组,它是基本类型的大小,而不是整个数组。

struct S1中,您有char后跟int。假设int是4个字节,这意味着ci之间需要3个字节的填充。因此具有隐式填充的结构如下所示:

struct S1
{
    char c;              // offset 0
    char padding[3];     // offset 1
    int i;               // offset 4
};

这会给我们sizeof(struct S1) == 8

然后在struct S3中,您有一个struct S1的实例,它是8个字节(但有4个字节对齐)和一个double,最可能是8个字节。因此,为了使它们正确对齐,c1之后需要3个字节的填充,然后在s之后再填充4个字节。所以现在使用隐式填充的struct S3如下所示:

struct S3
{
    char c1;            // offset 0
    char padding[3];    // offset 1
    struct S1 s;        // offset 4
    char padding[4];    // offset 12
    double c2;          // offset 16
};

然后我们有sizeof(struct S3) == 24

虽然这样的填充方案是您最有可能遇到的,但标准并不保证。

答案 2 :(得分:1)

C标准(到2011年)大多未指明。 2011年标准改变了这一点。

原则是每个数据类型都有一个对齐要求,由连续地址之间的字节数表示,可以分配(或存储)该类型的对象。

struct类型的地址也等于其第一个成员的地址(在所有C标准中,不仅仅是自2011年以来)。从2011年开始,这样做的结果是struct类型的对齐将是其第一个成员对齐的倍数。

struct的每个成员 - 不仅仅是第一个成员 - 还必须根据其类型进行对齐。例如,int成员的对齐要求为intdouble成员的对齐要求为double,数组的对齐要求等于数组(等于元素数乘以sizeof元素)。

最弱的对齐(最小的对齐要求)是charsigned charunsigned char的对齐,等于1。较大的类型,自然就足够了,具有更大的对齐要求。

实际上,实现会根据需要添加填充,以确保struct的每个成员都满足自己的对齐要求。

以上是过度简化 - 2011标准中引入了其他设施,我还没有描述,例如alignas会影响类型和对象的对齐方式。

答案 3 :(得分:0)

这是因为结构中的填充。计算机不会在任何地址上存储变量,它们会尝试将它们存储在4个字节的倍数上,如果它不能适应变量,它会在下一个4个字节后设置它们。

Address | Variable
--------|---------
1000    | char c
1001    | char d
1002    |             //Empty so that the next int can occupy 
1003    |             //  4 bytes
1004    |  int x     
1005    |    -
1006    |    -        //Filled till 1007 so next variable can 
1007    |    -        // start from 1008
1008    |    
1009    |  

C处理器遵循与结构相同的规则,因此它留下空间并尝试在4字节空间上拟合变量。

请看 The Lost art of Struct packing