您的位置:首页 > 编程语言 > C语言/C++

C语言中结构体的对齐规则

2017-06-01 20:57 330 查看
参考博客:

结构体的内存空间分配原理

结构体在内存中的对其规则

C/C++语言中结构体的内存分配小例子

结构体对齐是为了更加快速的读取结构体中的变量。对齐之后,多余的内存空间被“填充”了,其中不放任何数据。

1、结构体的对齐规则

结构体的成员是按顺序排列在内存地址中的,根据结构体的对齐规则,结构体中的元素顺序可能会影响结构体整体占用的字节数。

规则一:结构体中的第一个成员位置在偏移量0,之后每个变量的偏移量必须是它本身字节数的整数倍。

规则二:如果结构体中嵌套结构体,那么嵌套的结构体的偏移量必须是它最大成员的字节数的整数倍。

规则三:结构体的总偏移量必须是它最大成员字节数的整数倍。

对于C++中的类也是同样的规则。

2、结构体的对齐实例

用sizeof计算各类型的字节数,得到结果如下表

char1short2
int4float4
long8double8
void*8
以下是求偏移量和长度的函数:

typedef unsigned int ui;
#define addr(x) (ui)(long)(x)
template <typename T>
void GetOffset(T t)
{
ui startAddr = addr(&t);
cout << "a: 0" \
<< "\tb: " << addr(&t.b)-startAddr \
<< "\tc: " << addr(&t.c)-startAddr \
<< "\td: " << addr(&t.d)-startAddr \
<< "\nlen: "<< sizeof(t) << endl;
}

(1)结构体s1

结构体s1的定义是:

struct s1{
int a;  // 4
short b;// 2
long c; // 8
float d;// 4
};

计算的结果是:

s1
a: 0	b: 4	c: 8	d: 16
len: 24


存储空间表示如下:



(2)结构体s2

结构体s2的定义是:

struct s2{
char a; // 1
char b; // 1
short c;// 2
long d; // 8
};


计算的结果是:

s2
a: 0	b: 1	c: 2	d: 8
len: 16


存储空间表示如下:



(3)类s3

类s3的定义是:

class s3{
public:
char a;     // 1
long b;     // 8
short c;    // 2
char d;     // 1
};
计算的结果是:

s3
a: 0	b: 8	c: 16	d: 18
len: 24
存储空间表示如下:



(4)类s4

类s4的定义是:

class s4{
public:
char a;     // 1
char b;     // 1
short c;    // 4
long d;     // 8
};
计算的结果是:
s4
a: 0	b: 1	c: 2	d: 8
len: 16
存储空间表示如下:



可以看出,类s3和类s4中的元素是一样的,只是顺序有些许差别,但因为对齐规则的存在,导致了两者所占用的空间完全不同。

(5)结构体s5

结构体s5的定义是:

struct s5{
int a;      // 4
s4 b;       // 16 max 8
char c;     // 1
float d;    // 4
};
这里的第二个量嵌套了类s4,根据之前的计算结果得知该类占用的空间为16字节,其中最大类型是8字节。

计算的结果是:

s5
a: 0	b: 8	c: 24	d: 28
len: 32
存储空间表示如下:



3、指定对齐字节

对齐的指令为

#pragma pack(n)

#pragma pack(push, n)
作用是比较结构体中的最大宽度和指定的数,取其中较小的那个作为对齐字节数。

在计算结构体s1空间之前分别设定对齐字节数为4和16,则计算的结果分别是:

pack(4)
a: 0	b: 4	c: 8	d: 16
len: 20

pack(16)
a: 0	b: 4	c: 8	d: 16
len: 24
当对齐数为16时,因为最大宽度是8,小于16,所以存储方式不变;当对齐数设置为4时,小于最大宽度8,因而对齐数为4,存储方式如下图所示:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息