(C语言)结构体内存对齐

简介: 1.对齐规则2.示例例1 例2 例33.存在内存对齐的原因1.平台原因2.性能原因4.修改默认对齐数

1.对齐规则

(1)结构体的第一个成员放在偏移量(相较于结构体变量的起始位置)为0的位置


(2)从第二个成员起,之后的每个成员都要对齐到对齐数的整数倍的地址处


       对齐数:编译器默认的对齐数与该成员大小的较小值


       VS中默认为8


       Linux中无默认对齐数,对齐数就是成员自身大小


(3)结构体总大小为最大对齐数(所有成员对齐数的最大值)的整数倍


(4)如果出现嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍


(5)当出现数组,数组的对齐数为数组元素与默认对齐数的较小值


2.示例

(以下均在VS下实现)


例1

#include <stdio.h>structs1{
charc1;
inti;
charc2;
};
intmain()
{
printf("%d", sizeof(structs1));//12return0;
}


计算结果为12,我们结合内存分布图来计算


c1为char类型,占1个字节,第一个成员放在偏移量为0的位置,(char的对齐数为1)


i为int类型,占4个字节,因此从偏移量为4的位置开始存放


c2为char类型,占1个字节,1为c2的默认对齐数,因此在i的后面接着存放c2,放在偏移量为9的位置处


结构体的最大对齐数为4,结构体的总大小为最大对齐数的整数倍,此时已经使用了9个字节的空间,则结构体的大小为12

2.png


例2

#include <stdio.h>structs1{
charc1;
inti;
charc2;
};
structs2{
charc;
structs1s;
inti;
};
intmain()
{
printf("%d\n", sizeof(structs1));//12printf("%d\n", sizeof(structs2));//20return0;
}


计算结果为20


c为char类型,占1个字节,第一个成员放在偏移量为0的位置,(char的对齐数为1)


由例1计算得出s的大小为12,s为结构体类型,对齐到自己的最大对齐数的整数倍处,s中的3个成员分别为char、int、char类型,最大对齐数为4,因此s对齐到偏移量为4的地址空间处。


i为int类型,对齐数为4,因此对齐到偏移量为16的地址空间处。


此时已经使用20个字节的空间,结构体的最大对齐数为4,因此结构体的大小为20

3.png


例3

#include <stdio.h>structs3{
charc1;
intarr[2];
charc2;
};
intmain()
{
printf("%d\n", sizeof(structs3));//16return0;
}


c1为char类型,占1个字节,第一个成员放在偏移量为0的位置,(char的对齐数为1)


arr[2]为数组,当出现数组时,对齐数为元素大小与默认对齐数的最小值,arr[2]的元素为int类型,对齐数为4,因此对齐到偏移量为4的地址空间处


c2为char类型,占1个字节,1为c2的默认对齐数,因此在arr[2]的后面接着存放c2,放在偏移量为12的位置处


4.png



3.存在内存对齐的原因

1.平台原因

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


2.性能原因

数据结构(尤其是栈)应该尽可能地在自然边界上对齐。


原因:为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问


可以说,结构体的内存对齐是拿空间时间  


当在使用结构体时,为了满足对齐,同时节省空间,可将占用空间小的成员尽量集中在一起


4.修改默认对齐数

结构在对齐方式不合适时,可以自己修改默认对齐数


使用#pragma预处理指令,可以修改默认对齐数(通常设置为2的次方数)

#include <stdio.h>#pragma pack(4)//设置默认对齐数为4structs1{
//  成员大小  默认对齐数  对齐数charc;//  1    4  1doubled;//8    4  4inti;//   4    4  4};
#pragma pack()//取消设置的默认对齐数,还原为默认对齐数structs2{
//  成员大小  默认对齐数  对齐数charc;//  1    8  1doubled;//8    8  8inti;//   4    8  4};
intmain()
{
printf("%d %d", sizeof(structs1),sizeof(structs2));
return0;
}

struct s1

struct s2

6.png

目录
相关文章
|
6小时前
|
C语言
C语言之分支结构
C语言之分支结构
23 0
|
6小时前
|
C语言
C语言结构体内存对齐
C语言结构体内存对齐
|
6小时前
|
存储 编译器 Linux
【C语言】自定义类型:结构体深入解析(二)结构体内存对齐&&宏offsetof计算偏移量&&结构体传参
【C语言】自定义类型:结构体深入解析(二)结构体内存对齐&&宏offsetof计算偏移量&&结构体传参
|
6小时前
|
C语言
【精通C语言】:分支结构if语句的灵活运用
【精通C语言】:分支结构if语句的灵活运用
24 1
|
6小时前
|
编译器 Linux C语言
C语言:结构体(自定义类型)知识点(包括结构体内存对齐的热门知识点)
C语言:结构体(自定义类型)知识点(包括结构体内存对齐的热门知识点)
|
6小时前
|
Java C语言 C++
C语言中用switch语句实现多分支选择结构
C语言中用switch语句实现多分支选择结构
21 0
|
6小时前
|
存储 编译器 C语言
C语言之结构体内存对齐与内存的简单理解
C语言之结构体内存对齐与内存的简单理解
|
6小时前
|
存储 Serverless C语言
C语言程序的结构
C语言是一种广泛使用的编程语言,其程序结构清晰,易于理解。下面我们将详细探讨C语言程序的基本结构,并通过一个示例代码来展示这些组成部分是如何协同工作的。 一、C语言程序的基本结构
16 0
|
6小时前
|
C语言
C语言:内存函数(memcpy memmove memset memcmp使用)
C语言:内存函数(memcpy memmove memset memcmp使用)