struct {
uint8_t foo;
uint8_t bar;
uint8_t baz;
uint8_t foos[252];
uint8_t somethingOrOther;
} A;
struct {
uint8_t foo;
uint8_t bar;
uint8_t baz;
uint8_t somethingOrOther;
uint8_t foos[252];
} B;
我在第一个例子中将字符串放在字节3上,而在B中的字节4上放置起来是否重要?
C中的数组是否必须开始对齐?
这个结构的大小是否恰好是256个字节?
答案 0 :(得分:4)
鉴于数据类型为uint8_t
(相当于unsigned char
),无论如何排序,都不需要在结构中填充。因此,在这种情况下,您可以合理地假设每个编译器都将该结构设置为256个字节,而不管元素的顺序如何。
如果有不同大小的数据元素,那么您可能会添加填充,结构的大小可能会因元素的顺序而异。
答案 1 :(得分:2)
不,没关系。
通过在必要的字段之间插入隐藏的“填充字节”,几乎每个编译器都会将struct
字段与适合目标体系结构的自然边界对齐。
具体来说,由于您只使用uint8_t
,因此不会插入填充字节 - 每个字段都已经落在自然对齐的边界上。 (一切都是一个的倍数。)
您显示的两个struct
的大小恰好是256个字节。您可以这样确认:
int main(void)
{
printf("sizeof(struct A)=%zu \n", sizeof(struct A));
printf("sizeof(struct B)=%zu \n", sizeof(struct B));
}
您可以通过“打包”结构来阻止添加此填充:
#pragma pack(1)
__attribute__((packed))
请注意,在具有未对齐成员的结构上执行此操作会对程序的性能产生严重影响。
答案 2 :(得分:2)
如the good book所述(C11第6.7.2.1节第14段):
结构或联合对象的每个非位字段成员都对齐 一种适合其类型的实现定义方式...... 可能是结构对象中未命名的填充
你没有“把foos
放在字节3上” - 除了第一个元素总是在字节0上的事实之外,你没有真正控制元素将放在哪个字节上。如果编译器认为可以提供最有效的访问,则可以为每个字段提供一个或多个机器字。如果是这样,它将在两者之间分配“填充”字节 - 未使用的空间。
请注意,这仅适用于结构;数组本身不添加任何填充字节(如果他们这样做,指针算术/索引规则将不起作用),所以你可以确定foos
本身的大小正是声明的大小,并且知道确切的每个编号元素的对齐。