close

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