目录
结构体的内存对齐:
举例&提出疑问?
内存对齐:
对齐规则:
偏移数:类似于数组的下标,指的是结构体每个成员的首个地址距离结构体起始位置的距离。
用结构体内存对齐的图例示范:——使用以上文代码进行举例
结构体嵌套的内存对齐
内存对齐的原因:
修改默认对齐数
结构体的内存对齐:
举例&提出疑问?
举例:
struct S1
{
char c1;
int i;
char c2;
};
int main()
{
printf("%d\n",sizeof(struct S1));
return 0;
}
以上代码是寻求一个结构体在内存中所占的字节大小。
按照平常的逻辑理论,这里的结构体大小理论上说,应该是六个字节,因为成员c1占一个字节,成员i占四个字节,成员c2占一个字节,所以加在一起一共是6个字节。
但答案真是如此吗?
结果算出的是12个字节。
而后,我又将结构体的成员顺序进行调换,结果还会是12个字节吗?
struct S1
{
char c1;
char c2;
int i;
};
int main()
{
printf("%d\n",sizeof(struct S1));
return 0;
}
通过运算,我们得知,最后得到的是八个字节。
是不是很奇怪,明明成员内容都是一样的,只不过调换了顺序,最后结构体的字节大小却发生了改变,这是为什么?
其实这是和结构体的内存对齐有关!
内存对齐:
对齐规则:
1. 结构体的第⼀个成员对⻬到相对结构体变量起始位置偏移量为0的地址处
2. 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。
对⻬数 = 编译器默认的⼀个对⻬数 与 该成员变量⼤⼩(变量的字节大小)的较⼩值。
VS中默认的值为8
Linux中没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩
3. 结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的 整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构 体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍。
struct S1
{
char c1;
int i;
char c2;
};
偏移数:类似于数组的下标,指的是结构体每个成员的首个地址距离结构体起始位置的距离。
用结构体内存对齐的图例示范:——使用以上文代码进行举例
struct S1
{
char c1;
char c2;
int i;
};
上述代码也是如此:
结构体嵌套的内存对齐
在掌握普通结构体的所占内存和对齐后,那么关于结构体嵌套的对齐值和内存该如何计算呢?
struct S3
{
double d;
char c;
int i;
};
struct S4
{
char c1;
struct S3 s3;
double d;
};
printf("%d\n", sizeof(struct S4));
先求第一个struct S3的所占内存:
再求struct S4所占的内存:
内存对齐的原因:
struct S
{
char c;
int i;
};
假设以上是一段内存,前面一段是不用内存对齐的模式,后面一段是使用内存对齐的模式。
二者看似毫无关系,且我们还觉得第二个模式还会浪费内存。
但是,内存对齐其实是一种那空间换取时间的操作。
为什么呢?这其实是和编译器的读取有关,vs编译器是32位机器,所以读取字节是一次读四个,而后要当你的结构体第一个成员是char第二个成员是int 时,且不进行对齐那么要读两次内存。
甚至不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定 类型的数据,否则抛出硬件异常。
修改默认对齐数
#include <stdio.h>
#pragma pack(8)//设置默认对齐数为8
struct s1
{
char c1;
int i;
char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认