Talk:c/language/object
来自cppreference.com
问题
运行此代码
#include <stdio.h>
#include <stdalign.h>
struct X
{
double a;
char b[5];
char c;
int d;
char e;
float f;
}k;
int main(void)
{
printf("sizeof(struct X) = %zu\n", sizeof(struct X));// why the value is 32?
printf("alignof(struct X) = %zu\n", alignof(struct X));
}
可能的输出:
sizeof(struct X) = 32
alignof(struct X) = 8
回复
详细的结构体的内存对齐规则请查阅资料,以下为简易的概括:
1) 结构体的第一个成员在与结构体变量偏移量为"0"的地址处存放。
2) 结构体的其他成员要存放到对齐数(取成员类型大小与默认对齐数的较小值)的整数倍的地址处。
3) 结构体的总大小为当前已存放的总内存大小(包括空位填充)扩展到结构体中每个成员的对齐数中的最大对齐数的整数倍。
4) 如果出现嵌套结构体的情况,则嵌套的结构体对齐到自己最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
以下示例不同平台下默认对齐数有差异:
运行此代码
#include <stdio.h>
#include <stddef.h>
struct X
{
double a; //成员对象大小:8,存放在偏移量为0的地址处,对齐数(取成员类型大小与默认对齐数的较小值)为8。
char b[5]; //成员对象大小:5,存放在对齐数(取成员类型(此处为元素类型)大小与默认对齐数的较小值)为1的整数倍的地址处,即偏移量为8的地址处。
char c; //成员对象大小:1,存放在对齐数(取成员类型大小与默认对齐数的较小值)为1的整数倍的地址处,即偏移量为13的地址处。
int d; //成员对象大小:4,存放在对齐数(取成员类型大小与默认对齐数的较小值)为4的整数倍的地址处,即偏移量为16的地址处。
char e; //成员对象大小:1,存放在对齐数(取成员类型大小与默认对齐数的较小值)为1的整数倍的地址处,即偏移量为20的地址处。
float f; //成员对象大小:4,存放在对齐数(取成员类型大小与默认对齐数的较小值)为4的整数倍的地址处,即偏移量为24的地址处。
}k;//结构体对象大小: 32,是当前已存放的总内存大小(包括空位填充)扩展到每个成员的对齐数的最大对齐数的整数倍,也就是对齐数8整数倍,故大小为32字节。
int main()
{
printf("%zu\n", offsetof(struct X, a));//得出"struct X"类型的成员"a"的偏移量是:0。
printf("%zu\n", offsetof(struct X, b));//得出"struct X"类型的成员"b"的偏移量是:8。
printf("%zu\n", offsetof(struct X, c));//得出"struct X"类型的成员"c"的偏移量是:13。
printf("%zu\n", offsetof(struct X, d));//得出"struct X"类型的成员"d"的偏移量是:26。
printf("%zu\n", offsetof(struct X, e));//得出"struct X"类型的成员"e"的偏移量是:20。
printf("%zu\n", offsetof(struct X, f));//得出"struct X"类型的成员"f"的偏移量是:24。
return 0;
}
可能的输出:
0
8
13
16
20
24