为什么结构中只有“char”类型的成员没有填充?
我在结构中只声明了char
类型的成员。
#include struct st { char c1; char c2; char c3; char c4; char c5; }; int main() { struct st s; printf("%zu\n", sizeof(s)); return 0; }
输出: [ 现场演示 ]
5
那么,为什么结构中只有char
类型成员没有填充?
结构中的填充(大多数)存在以强制单个成员与其基本对齐要求对齐 ,即( C11 3.2p1 ):
要求特定类型的对象位于存储边界上,其地址是字节地址的特定倍数
结构的中间和末端的填充用于确保即使在这些结构的arrays内 ,每个构件仍将根据它们的对准要求对齐。 C11 6.2.8p1 :
完整对象类型具有对齐要求,这些要求对可以分配该类型的对象的地址施加限制。 对齐是实现定义的整数值,表示可以分配给定对象的连续地址之间的字节数。 对象类型对该类型的每个对象强制对齐要求:可以使用_Alignas关键字请求更严格的对齐。
现在,每个其他类型的对齐要求都是实现定义的,但有一点是隐含的:因为对齐要求用size_t
表示; sizeof (char)
是1,并且指向字符类型的指针可用于处理其他类型的每个单独字符,字符类型不能具有大于1的基本对齐要求。令人惊讶的是,这在C标准中根本没有详细说明; 它只是这个模糊的措辞( C11 6.2.8p6 ):
char
,signed char
和unsigned char
应具有最弱的对齐要求。
由于char
的对齐最多为1,编译器不需要添加任何填充,因为即使结构正好是5个字节长,那么即使在数组中,某些结构从奇数地址开始,这些结构的每个成员仍然会正确对齐。
填充是为了强制对齐 requeriments。 如果成员位于可被其大小整除的地址,则称该成员对齐 (其大小)。
在您的示例中不需要填充,因为st
结构的所有成员已经与其大小对齐,即: st
的每个成员的地址已经可以被其大小整除。 所有成员都是char
类型, char
的大小是1 。 如果成员的大小为1 ,则该成员始终与其大小对齐,因为任何地址都可以被1整除。
某些类型,正确对齐后,具有更好的性能/稳定性等。当这种类型的变量后面还有其他变量使其起始位置“未对齐”时,编译器可能决定添加填充以使对齐顺利。 这都是可选的,当然你没有必要的是字节( char
)。
如果您编写如下结构,您将更有可能观察填充:
struct pad{ int8_t a; int64_t b; }; assert(sizeof(struct pad) == 16);
其内存布局应如下所示:
|---|-------|---------| | 1 | 7 | 8 | |---|-------|---------| byte|padding|64-bit int
然后,不需要对齐字节,因为它们是最小的存储单元。