C语言学习笔记(14)
1. 位域
我们来看一个表示日期的结构体:
typedef struct { unsigned int year; unsigned int month; unsigned int day; }MyDate;
但是我们可以发现,其实year最大也不会超过四位数,month也就是12,而day最大也就是31。但是我们在上述的结构体中,却为其分配了4*3=12字节的内存,是不是很浪费呢?
C语言为了解决这个问题,提出了一个概念,叫位域。看段代码:
typedef struct { unsigned int year:7; unsigned int month:4; unsigned int day:5; }MyDate;
这个的意思是,我为结构体中的每一个字段分配指定的位数,比如,我为year分配了7位。这样就有效地节省了内存。
网上有着有限的几篇关于位域的文章,我觉得在CSDN的一个帖子中,对于关于位域分配内存的情况说的最为详细,原封不动地拿下来了:
C99规定int、unsigned int和bool可以作为位域类型,但编译器几乎都对此作了扩展,
允许其它类型类型的存在。
使用位域的主要目的是压缩存储,其大致规则为:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字
段将紧邻前一个字段存储,直到不能容纳为止;
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字
段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方
式,Dev-C++采取压缩方式;
4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。
2. 再谈联合体
在之前,我们谈到过使用联合体来节约内存空间,但是联合体也经常被用于一个其他的目的:从两个或更多的角度去看待内存块。
例如:
union int_Date { int i; MyDate dt; };
在上面的程序中,我们就可以用两种视角(整数视角和日期视角)来看待一个数据。
我们知道,在X86的机器中,我们常常会用到4个16位寄存器,这四个16位寄存器又可以分成8个8位的寄存器。例如,当我们改变ax的时候,其实al和ah也同时发生了改变,那么我们可以把这个关系用联合体来表示。
typedef union { struct { short ax,bx,cx,dx; }word; struct { char al,ah,bl,bh,cl,ch,dl,dh; }byte; }Regs; int main (void) { Regs regs; regs.byte.ah=0x12; regs.byte.al=0x34; printf("%x",regs.word.ax); return 0; }
3. volatile限定符
volatile告诉编译器,这段内存空间所存储的值是易变的。volatile通常用于指向易变内存空间的指针。有个例子我觉得非常恰当。
我们假设*p指向的内存空间用于存放用户通过键盘所输入的字符,然后我们读取到这个字符,再将其放入到一个数组中。
但是一些优秀的编译器会发现,在这个过程中,p和*p都未被程序显式地改变,这样编译器就会对其作出优化,使*p只被取一次,这样就读入了数组中一些重复的数据,这明显不是我们想要的。
但是当我们在*p前加上volatile限定符,其实就是在告诉编译器,不要对该段程序进行优化,因为这段程序是易变的,每次的读取都要从内存中去重新取得。
在C#中也有volatile关键字,目的也是一样,volatile关键字代表某个变量可能会被多个并发的线程进行修改,所以通知编译器不要对其进行优化,这样就能保证每次取出来的值不是被缓存的,而是最新的值。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
2009-04-17 一步一步学WF系列(五)——工作流模拟猜数游戏
2009-04-17 一步一步学WF系列(四)——工作流模拟登陆