我知道在 C 中,结构体成员的顺序是它们声明的顺序加上(通常,除非另有说明)可能会发生填充,导致我创建的前两个结构体具有各自的大小:
struct MyStructV1
{
int a;
char c;
int b;
};
printf("size of MyStructV1 is:%lu \n",sizeof(struct MyStructV1)); // prints 12
struct MyStructV1Packed
{
int a;
char c;
int b;
}__attribute__((__packed__));;
printf("size of MyStructV1Packed is:%lu \n",sizeof(struct MyStructV1Packed)); // prints 9
到目前为止一切顺利。
我的问题是,以下声明的“解压”版本的 MyStructV2 与 MyStructV1 的第一个版本相比是否有任何好处/优点?
struct MyStructV2
{
int a;
int b;
char c;
};
printf("size of MyStructV2 is:%lu \n",sizeof(struct MyStructV2)); // prints 12 as well
请注意,现在成员的顺序发生了变化(b 在 c 之前声明)。
我指的是需要完成内存访问“成本”或周期才能读/写结构成员和/或任何其他相关的考虑因素?
它是否依赖于编译器/架构(如果有的话)?
干杯,
家伙。
第一个版本和最后一个版本之间应该没有什么区别。在这两个结构中,
int
成员在字边界上对齐,因此可以有效地从内存中读取它们。它们之间唯一的区别是,填充位于 c
中的 b
和 MyStructV1
之间,以及 MyStructV2
中结构的末尾。但不会因为填充而产生执行开销;访问结构体成员只需将已知偏移量添加到结构体开头的地址即可完成。在 MyStructV1
中,b
的偏移量是 8
,在 MyStructV2
中,它是 4
。
如果
char
小于 int
(通常是这样),则结构 MyStructV1
可以小于 MyStructV2
。
根据环境(体系结构和编译器选项),struct
MyStructV1
可以包围焊盘,也可以错位 b
。
根据架构的不同,如果 b
加载未对齐,则可能需要更多 CPU 时钟。
此外,根据架构的不同,读取 a 可以加载更多内容以便立即可用,如果有填充,则这种好处会减少或丢失。
这更有趣,当然订购也很重要。
struct aaa1{
char a;
char a1;
int b;
};
struct aaa2{
char a;
char a1;
char a2;
int b;
};
struct aaa3{
char a;
char a1;
char a2;
char a3;
int b;
};
struct aaa4{
char a1;
char a2;
char a3;
int b;
char a;
};
int main(void) {
struct aaa5{
char a;
int b;
char a1;
};
printf("%zu %zu %zu %zu %zu %zu\n", sizeof(struct aaa), sizeof(struct aaa1), sizeof(struct aaa2), sizeof(struct aaa3), sizeof(struct aaa4), sizeof(struct aaa5));
输出:8 8 8 8 12 12