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)”,然而,我发现它不是真的。谢谢你的帮助。
答案 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个字节,这意味着c
和i
之间需要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
成员的对齐要求为int
,double
成员的对齐要求为double
,数组的对齐要求等于数组(等于元素数乘以sizeof
元素)。
最弱的对齐(最小的对齐要求)是char
,signed char
和unsigned 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字节空间上拟合变量。