公司网站推广费用,咸宁响应式网站建设价格,齐鲁网,源码下载网站有哪些目录
一、结构体内存对齐规则#xff1a;
1.1范例
1.2结构体内存对齐规则
1.3自定义默认对齐数
二、位段
2.1什么是位段
2.2位段的内存分配
2.3位段的不足
三、枚举和联合体
3.1枚举
3.1.1枚举类型的定义
3.1.2枚举类型的使用
3.2联合体
3.2.1联合体的定义
3.…目录
一、结构体内存对齐规则
1.1范例
1.2结构体内存对齐规则
1.3自定义默认对齐数
二、位段
2.1什么是位段
2.2位段的内存分配
2.3位段的不足
三、枚举和联合体
3.1枚举
3.1.1枚举类型的定义
3.1.2枚举类型的使用
3.2联合体
3.2.1联合体的定义
3.2.2联合体的特点 一、结构体内存对齐规则
1.1范例
我们来看一下结构体所占用的内存大小 命名 A 和 B 的结构体成员都一样 但是为什么他们占用的内存空间不一样呢下面我们来介绍一下结构体内存的对齐规则。
1.2结构体内存对齐规则
首先我们要知道什么是对齐数对齐数 编译器中默认的对齐数 与 该成员类型变量的大小单位是byte中的较小值。其中VS默认的对齐数是8Linux无默认对齐数对齐数是其本身。
而在结构体中存放的数据其地址并不是严格连续存放的而是存放在其对齐数的整数倍。
编译器为结构体开创的大小是最大对齐数的整数倍。
struct stu
{char name[20];int age;double grades;
};
int main()
{printf(%d\n, sizeof(struct stu));//结果为32return 0;
} 1.3自定义默认对齐数
之前在我们写三子棋时创建的 .h 文件中我们就见过 #pragma 这个预处理指令这里我们再次使用可以改变我们的默认对齐数。 #pragma pack(8)//设置默认对齐数为8
struct A
{int a;short b;int c;char d;
};#pragma pack()//取消设置的默认对齐数还原为默认
#pragma pack(1)//设置默认对齐数为1struct B
{int a;short b;char c;int d;
};当我们把结构体 A 和 B 的默认对齐数都设置为1时我们可以再次计算一下他们的大小 可以看出他们的内存竟然都变成了11这也说明了我们设置的默认对齐数起作用了。
二、位段
2.1什么是位段
很多朋友可能是第一次听说过位段它是什么为什么能和结构体扯上关系
接下来我们对比一下位段类型的结构体和正常的结构体 不难看出来位段类型是在我们正常定义的变量基础上加上了 :数字 。其实这代表了我们定义的变量所需要占用的存储空间单位是 bit 。
我们分别来计算上面两种结构体的大小我们可以得出使用位段的结构体只需要8字节不使用位段的结构体却要16个字节。所以位段是用来节省空间的。
2.2位段的内存分配
我们来看个例子了解在VS中位段的内存分配。 #includestdio.hstruct _Record_Struct
{unsigned char Env_Alarm_ID : 4;unsigned char Para1 : 2;unsigned char state;unsigned char avail : 1;
};int main()
{sizeof(struct _Record_Struct);return 0;
} 我们在VS中运行这个程序也可以得到结果是3(byte)和我们图中的一样。 位段虽然能节省空间但当两个位段类型超过 1byte 时还是会浪费第一个位段类型剩余的几个 bit 开辟下一个字节空间来存放第二个位段类型 我们再来看个例子来更直观的感受每一个 bit 位是怎么分配的。
struct S
{char a : 3;char b : 4;char c : 5;char d : 4;
};
int main()
{struct S s { 0 };s.a 10;s.b 12;s.c 3;s.d 4;return 0;
} 接下来我们通过内存看一下他们存放的数据每四个bit位在内存中对应一个十六进制数字 事实证明我们的理解是对的
2.3位段的不足
我们上述只是讲解了VS中位段空间的分配但是这仅仅是在VS中...... 1. int 位段被当成有符号数还是无符号数是不确定的。 2. 位段中最大位的数目不能确定16位机器最大1632位机器最大32写成27在16位机器会出问题。。 3. 位段中的成员在内存中从左向右分配还是从右向左分配标准尚未定义。 4. 当一个结构包含两个位段第二个位段成员比较大无法容纳于第一个位段剩余的位时是舍弃剩余的位还是利用这是不确定的。 三、枚举和联合体
接下来我们介绍两种和结构体类似的自定义类型枚举和联合体
3.1枚举
3.1.1枚举类型的定义
我们先来看一下枚举的语法
enum Day//星期
{Mon,Tues,Wed,Thur,Fri,Sat,Sun
};
enum 命名枚举中的类型用 , 隔开。
这些可能取值都是有值的默认从0开始一次递增1当然在定义的时候也可以赋初值。赋初值后定义的类型取值从初值开始递增1如
enum Day
{Mon,//0Tues 2,//2Wed,//3Thur,//4//......Fri,Sat,Sun
};
3.1.2枚举类型的使用
枚举类型能怎么使用呢 其实它的使用在我们写一些小应用时用到的概率大一点
enum Day//星期
{Mon 1,Tues,Wed,Thur,Fri,Sat,Sun
};int main()
{int input 0;scanf(%d, input);switch (input){case Mon:case Tues:case Wed:case Thur:case Fri:printf(今天是工作日\n); break;case Sat:case Sun:printf(今天可以休息一下啦\n); break;}return 0;
}
当我们用枚举常量代替 case 情况的取值时我们的代码是不是变得清晰易懂 枚举的优点 1. 增加代码的可读性和可维护性 2. 和#define定义的标识符比较枚举有类型检查更加严谨。 3. 防止了命名污染封装 4. 便于调试 5. 使用方便一次可以定义多个常量 3.2联合体
3.2.1联合体的定义
联合也是一种特殊的自定义类型这种类型定义的变量也包含一系列的成员特征是这些成员公用同一块空间所以联合也叫共用体。 比如
//联合类型的声明
union Un
{char c;int i;
};
//联合变量的定义
union Un un;
//计算连个变量的大小
printf(%d\n, sizeof(un)); union 命名成员之间用 ; 相隔。
3.2.2联合体的特点 联合的成员是共用同一块内存空间的这样一个联合变量的大小至少是最大成员的大小因为联合至少得有能力保存最大的那个成员。 联合体占用空间也遵循结构体对齐规则。