整理今天的学习内容
1.结构体实现位段
(1)位段的声明
位段的成员必须是 int、unsigned int 或signed int ,在C99中位段成员的类型也可以选择其他类型
例:
(2)位段的内存分配
位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式开辟的
解释下面程序的运行结果
首先开辟四个字节,32个比特位,_a,_b,_c,依次放入被开辟空间中
当_d申请30个比特位的空间时,原先开辟的空间不够,再次开辟4个字节的空间存放_d,其余空间被浪费掉
注:一个空格代表1个比特位
所以struct A 变量的大小是8个字节
测试:
注:一个空格代表1个比特位
(3)位段的跨平台问题
·int 位段被当成有符号数还是无符号数是不确定的
·位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机器会出问题
·位段中的成员在内存中从左向右分配,还是从右向左分配,标准尚未定义
·当⼀个结构包含两个位段,第二个位段成员比较大,无法容纳于第⼀个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的
·跟结构相比,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在
(4)位段的使用
位段的几个成员共用同⼀个字节,所以不能对位段的成员使用&操作符,这样就不能使用scanf直接给位段的成员输入值,只能是先输入放在一个变量中,然后赋值给位段的成员
例:
自定义类型:联合和枚举
1.联合体
(1)联合体类型的声明
(2)联合体在内存中的储存
编译器只为联合体最大的成员分配足够的内存空间,联合体的特点是所有成员共用同⼀块内存空间。所以联合体也叫:共用体
给联合体其中一个成员赋值,其他成员的值也跟着变化
(3)联合体大小的计算
1.联合的大小至少是最大成员的大小
2. 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍
(4)结构体和联合体的对比
例:图书、杯子、衬衫这三种商品每⼀种都有:库存量、价格、商品类型的信息,除此之外,图书还包括书名、作者、页数,杯子还包括设计,衬衫还包括设计、可选颜色、可选尺寸
以结构体的的形式设计变量:
以联合体的的形式设计变量:
与结构体相比,联合体的使用可以节省内存
(5)用联合体判断当前机器的大小端
2.枚举
(1)枚举的声明
{}中的内容是枚举类型的可能取值,也叫枚举常量 。
这些可能取值都是有值的,默认从0开始,依次递增1,当然在声明枚举类型的时候也可以赋初值
(2)枚举类型的优点
·增加代码的可读性和可维护性
· 和#define定义的标识符比较枚举有类型检查,更加严谨
·便于调试,预处理阶段会删除 #define 定义的符号
· 使用方便,一次可以定义多个常量
·枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用
(3)枚举类型的使用
使用枚举常量给枚举变量赋值
C语言中可以拿整数直接给枚举变量赋值,但在C++中不行,因为C++的类型检查比较严格
动态内存管理
C语言中的动态内存开辟使程序员可以自己申请和释放空间
1.malloc和free
(1)malloc
void* malloc (size_t size);
↑
需要开辟空间的字节数
这个函数向内存申请⼀块连续可用的空间,并返回指向这块空间的指针
• 如果开辟成功,则返回⼀个指向开辟好空间的指针
• 如果开辟失败,则返回⼀个 NULL 指针,因此malloc的返回值⼀定要做检查
• 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候由使用者自己决定
• 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器
(2)free
void free (void* ptr);
↑
需要释放的动态内存的地址
free函数用来释放动态开辟的内存
• 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的
• 如果参数 ptr 是NULL指针,则函数不进行任何处理
malloc和free都声明在 stdlib.h 头文件中
使用free函数处理过的指针是野指针,需要置NULL
2.calloc和realloc
(1)calloc
void* calloc (size_t num, size_t size);
• 函数的功能是为 num 个大小为 size 的元素开辟⼀块空间,并且把空间的每个字节初始化为0
• 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全 0
calloc函数的使用:
(2)realloc
void* realloc (void* ptr, size_t size);
realloc 函数可以对动态开辟内存大小进行调整
• ptr 是要调整的内存地址
• size为调整之后新大小
• 返回值为调整之后的内存起始位置
• 这个函数调整原内存空间大小的基础上,还可能会将原来内存中的数据移动到新的空间
realloc在调整内存空间时存在两种情况:
情况1:原有空间之后有足够大的空间
直接原有内存之后直接追加空间,原来空间的数据不发生变化
情况2:原有空间之后没有足够大的空间
在堆空间上另找⼀个合适大小 的连续空间来使用,这样函数返回的是⼀个新的内存地址
realloc函数的使用:
realloc(NULL,20)==malloc(20)