-
-
[旧帖] [原创](15PB) C语言结构体大小及对齐问题 0.00雪花
-
发表于: 2016-1-4 11:31 1420
-
0.问题的提出
写出一个struct,然后sizeof,会发现sizeof的结果往往比声明的变量总长度大,这是因为内存对齐问题而造成的。
1.对齐的意义
许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的起始地址的值是某个数k的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数。这种强制的要求一来简化了处理器与内存之间传输系统的设计,二来可以提升读取数据的速度。
2.对齐的原则
对齐采用的总体原则是这样的:4字节变量的存放要对齐到可以被4整除的地址上,8字节变量的存放要对齐到可以被8整除的地址上。
原则A:struct或者union的成员,第一个成员在偏移0的位置,之后的每个成员的起始位置必须是当前成员大小的整数倍;
原则B:如果结构体A含有结构体成员B,那么B的起始位置必须是B中最大元素大小整数倍地址;
原则C:结构体的总大小,必须是内部最大成员的整数倍;
3. 举例说明
struct _TEST1
{
char c;
int i;
double d;
} g_stcTest;
struct _TEST2
{
char c;
double d;
int i;
} g_stcTest2;
struct _TEST3
{
double d;
char c;
int i;
} g_stcTest3;
对3个结构体sizeof的结果分别为16 24 16
对TEST1而言,其内存空间分配如下:(原则2)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
c1 i1 i2 i3 i4 d1 d2 d3 d4 d5 d6 d7 d8
c为char类型,占1个字节,从偏移为0的地址开始;i为int 类型,占4个字节,其起始位置应为4的整数倍,即从偏移为4的位置开始连续占4个字节;d为double类型,占8个字节,其其实位置应为8的整数倍,即从偏移为8的位置开始连续占用8个字节。最后对整个结构体占用字节数进行检查,发现一共占用16字节数,为结构体内最长类型double的整数倍;因此TEST1结构占用字节数为16。
对TEST2而言,其内存空间分配如下:(原则3)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
c1 d1 d2 d3 d4 d5 d6 d7 d8 i1 i2 i3 i4
c为char类型,占1个字节,从偏移为0的地址开始;d为double类型,占8个字节,其起始位置应为8的整数倍,即从偏移为8的位置开始连续占用8个字节。i为int 类型,占4个字节,其起始位置应为4的整数倍,即从偏移为16的位置开始连续占4个字节;最后对整个结构体占用字节数进行检查,发现一共占用20字节数,不是结构体内最长类型double的整数倍,需补齐,补四位为24,此时为double的整数倍;因此TEST1结构占用字节数为24。
TEST3同TEST1不再赘述。
4.空间
在设计结构体时,一般会将占用空间小的类型排在前面,占用空间大的类型排在后面,这样可以节约一些对齐空间。
写出一个struct,然后sizeof,会发现sizeof的结果往往比声明的变量总长度大,这是因为内存对齐问题而造成的。
1.对齐的意义
许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的起始地址的值是某个数k的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数。这种强制的要求一来简化了处理器与内存之间传输系统的设计,二来可以提升读取数据的速度。
2.对齐的原则
对齐采用的总体原则是这样的:4字节变量的存放要对齐到可以被4整除的地址上,8字节变量的存放要对齐到可以被8整除的地址上。
原则A:struct或者union的成员,第一个成员在偏移0的位置,之后的每个成员的起始位置必须是当前成员大小的整数倍;
原则B:如果结构体A含有结构体成员B,那么B的起始位置必须是B中最大元素大小整数倍地址;
原则C:结构体的总大小,必须是内部最大成员的整数倍;
3. 举例说明
struct _TEST1
{
char c;
int i;
double d;
} g_stcTest;
struct _TEST2
{
char c;
double d;
int i;
} g_stcTest2;
struct _TEST3
{
double d;
char c;
int i;
} g_stcTest3;
对3个结构体sizeof的结果分别为16 24 16
对TEST1而言,其内存空间分配如下:(原则2)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
c1 i1 i2 i3 i4 d1 d2 d3 d4 d5 d6 d7 d8
c为char类型,占1个字节,从偏移为0的地址开始;i为int 类型,占4个字节,其起始位置应为4的整数倍,即从偏移为4的位置开始连续占4个字节;d为double类型,占8个字节,其其实位置应为8的整数倍,即从偏移为8的位置开始连续占用8个字节。最后对整个结构体占用字节数进行检查,发现一共占用16字节数,为结构体内最长类型double的整数倍;因此TEST1结构占用字节数为16。
对TEST2而言,其内存空间分配如下:(原则3)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
c1 d1 d2 d3 d4 d5 d6 d7 d8 i1 i2 i3 i4
c为char类型,占1个字节,从偏移为0的地址开始;d为double类型,占8个字节,其起始位置应为8的整数倍,即从偏移为8的位置开始连续占用8个字节。i为int 类型,占4个字节,其起始位置应为4的整数倍,即从偏移为16的位置开始连续占4个字节;最后对整个结构体占用字节数进行检查,发现一共占用20字节数,不是结构体内最长类型double的整数倍,需补齐,补四位为24,此时为double的整数倍;因此TEST1结构占用字节数为24。
TEST3同TEST1不再赘述。
4.空间
在设计结构体时,一般会将占用空间小的类型排在前面,占用空间大的类型排在后面,这样可以节约一些对齐空间。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
看原图
赞赏
雪币:
留言: