我已经提到过Intl.v8BreakIterator,但仍然无法找到以下情况的答案。
为什么填充不适用于test1
的情况?
#include <stdio.h>
typedef unsigned short u16;
typedef unsigned char u8;
typedef struct
{
u8 a[5];
u8 b;
u8 c;
} test1;
typedef struct
{
u8 a[5];
u16 b;
} test2;
int main(void) {
test1 t1;
test2 t2;
printf("t1 = %d\n", sizeof(t1));
printf("t2 = %d\n", sizeof(t2));
return 0;
}
Output:
t1 = 7
t2 = 8
在来自@ryyker和@Ajay Brahmakshatriya的答案之后,我做了另一个测试代码,看来答案不适用于这种情况...如果填充大小为3,因为类型为{{1} }是3,为什么test1
的大小不是9而不是7?
test2
答案 0 :(得分:0)
结构的对齐要求大于等于其每个成员的对齐要求。另外,数组的对齐要求与其元素的对齐要求相同。
如果u8
的对齐要求为1个字节,u16
的对齐要求为2个字节,则test1
的对齐要求将至少为1个字节,而{{ 1}}至少应为2个字节。
由于test2
的对齐要求是2个字节,因此它的大小也应该是2个字节的倍数(这样,如果您声明该结构的数组,则该数组的所有元素都可以正确对齐) 。
test2
的元素大小之和为7个字节。 2的最接近倍数是8个字节。
对于test2
,由于对齐要求仅为1个字节,因此7是可接受的大小。
最后,只要满足上述所有约束,这些实现就可以向结构中添加任意数量的填充。因此,没有正确的方法来回答“为什么此结构的大小不等于我所计算的大小?”的问题。我在这里可能是关于为什么您的实现选择了当前大小的理由。
答案 1 :(得分:0)
为什么填充不适用于test1 ......因为字节是最小的自然内存段,而对于第一个struct
,仅 类型,编译器为此struct
在一个字节段设置内存对齐方式。没有一个成员反对这种自然的统一。因此,不需要填充。
在第二个结构定义中,有一种u16
类型,并且在数组成员中存储了奇数个字节(5)。 u16
成员导致对齐边界(|
)(默认情况下)为两个字节:
第一个结构可以看做是一系列字节存储位置,具有1个字节对齐:
|.......|.......|.......|.......|.......|.......|.......| ( 7-bytes )
a[0] a[1] a[2] a[3] a[4] b c
具有u16
成员的第二个结构使用2字节对齐:(因此也会导致填充。)
|...............|...............|...............|..............| (8-bytes )
a[0] a[1] a[2] a[3] a[4] (padding) b
请注意,可以使用pragma
语句修改默认的对齐边界。例如,pragma pack(1)
将对齐边界强制为1个字节。这将有效地将b
与a[4]
相邻放置在内存中,并使第二个结构的大小与第一个相同。
|.......|.......|.......|.......|.......|.......|.......| ( 7-bytes )
a[0] a[1] a[2] a[3] a[4] b
pragma pack(1)//force alignment to 1 byte
typedef struct
{
u8 a[5];
u16 b;
} test2;
pragma pack()// set packing back to what it was
尽管this question/answer谈论了pragma
语句,但它涵盖了周围的概念,例如您所要求的概念。