结构体的简单介绍(3)——结构体的内存对齐

目录

结构体的内存对齐:

举例&提出疑问?

 内存对齐:

对齐规则:

偏移数:类似于数组的下标,指的是结构体每个成员的首个地址距离结构体起始位置的距离。

用结构体内存对齐的图例示范:——使用以上文代码进行举例

结构体嵌套的内存对齐 

内存对齐的原因: 

修改默认对齐数 



结构体的内存对齐:

举例&提出疑问?

举例:

struct S1
{
 char c1;
 int i;
 char c2;
};

int main()
{

 printf("%d\n",sizeof(struct S1));
 return 0;

}

以上代码是寻求一个结构体在内存中所占的字节大小。

按照平常的逻辑理论,这里的结构体大小理论上说,应该是六个字节,因为成员c1占一个字节,成员i占四个字节,成员c2占一个字节,所以加在一起一共是6个字节。

但答案真是如此吗?

结构体的简单介绍(3)——结构体的内存对齐_第1张图片

结果算出的是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;
};

偏移数:类似于数组的下标,指的是结构体每个成员的首个地址距离结构体起始位置的距离。

结构体的简单介绍(3)——结构体的内存对齐_第2张图片

用结构体内存对齐的图例示范:——使用以上文代码进行举例

 结构体的简单介绍(3)——结构体的内存对齐_第3张图片

struct S1
{
 char c1;
 char c2;
 int i;
};

上述代码也是如此:

结构体的简单介绍(3)——结构体的内存对齐_第4张图片

 

结构体嵌套的内存对齐 

在掌握普通结构体的所占内存和对齐后,那么关于结构体嵌套的对齐值和内存该如何计算呢?

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的所占内存:

结构体的简单介绍(3)——结构体的内存对齐_第5张图片 再求struct S4所占的内存:

 结构体的简单介绍(3)——结构体的内存对齐_第6张图片

 

 

内存对齐的原因: 

struct S
{
  char c;
  int i;
};

 

假设以上是一段内存,前面一段是不用内存对齐的模式,后面一段是使用内存对齐的模式

二者看似毫无关系,且我们还觉得第二个模式还会浪费内存

但是,内存对齐其实是一种那空间换取时间的操作。

为什么呢?这其实是和编译器的读取有关,vs编译器是32位机器,所以读取字节是一次读四个,而后要当你的结构体第一个成员是char第二个成员是int 时,且不进行对齐那么要读两次内存。

甚至不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定 类型的数据,否则抛出硬件异常。

 

修改默认对齐数 

#include 
#pragma pack(8)//设置默认对齐数为8
struct s1
{
char c1;
int i;
char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认

你可能感兴趣的:(C++,C语言,数据结构,结构体,c语言,函数)