当前位置:网站首页>C语言位域
C语言位域
2022-07-16 10:35:00 【乔以亦】
前言
在之前工作中从未使用过这种形式,可能是一个公司一个编码风格吧,现在的公司里面大量代码定义时候都使用到了位域,作者在网上搜了一点资料看了一下,记录一下自己简单的理解。
位域简介
在信息存储时,有时我们很确切的知道某个值的范围,我们就可以使用位域来限制这个变量的取值范围,并且能节省内存。使用位域时
变量类型 变量 : 数值;
的意思是该变量仅占用数值对应值的比特位个数。并且数值对应值不应大于变量类型所占的最大比特位数。
例子
比如一个在结构体中有个值a取值范围是0-15那么我们在定义变量类型的时候就可以使用位域,使用位域可以节省内存空间,bc等值同理,为了方便理解多写几个值。写法如下
typedef struct
{
unsigned short a:4; //定义无符号字符形a ,a仅使用0-3比特位
unsigned short b:8; //定义无符号短整形b ,b仅使用4-11比特位
unsigned :12; //定义无符号整形起到占位作用,占12-23比特位
unsigned int c:2; //定义无符号整形c ,c仅使用24-25比特位
...
}Test;
int main(int argc, char *argv[])
{
Test b;
b.a=15;
printf("%d\n",b.a); //输出结果为15,15二进制为 1111
}
下面让我们看下如果赋值超出位域范围会出现什么情况:
int main(int argc, char *argv[])
{
Test b;
b.a=16;
printf("%d\n",b.a); //输出结果为0,16的二进制为 0001 0000
}
这里我们就可以看出其实在解析变量时实际仅解析的位域限制位数的值,也就是 0000前面的0001并没有被解析因此输出是0。那么我就可以猜测如果赋值为17输出应该为1。下面验证:
int main(int argc, char *argv[])
{
Test b;
b.a=17;
printf("%d\n",b.a); //输出结果为1,17二进制为 0001 0001
}
果然证实了我们的猜测。
下面我们在测试下如果赋值大于了类型取值范围但是没有大于位域的取值范围会出现什么情况:
typedef struct
{
unsigned char a:16;
unsigned short b:16;
}Test;
int main(int argc, char *argv[])
{
Test b;
b.a=257;
b.b=257;
printf("a = %d\n b = %d\n",b.a,b.b); //输出结果为 a = 1 b = 257
}
我们知道unsigned char 8个比特位取值范围为0到2^8-1也就是0-255。当我们输入一个大于255的数无论多大只取该数对应的最后8个比特位257二进制为 0001 0000 0001,unsigned char a:16; 位域定义的是16位,但是unsigned char 本身只有8位因此会按照8个比特位解析也就是解析的0000 0001,输出结果就是1。而unsigned short b:16;位域定义是16位,unsigned short占用内存也是16个比特位,所以b解析时候会按照16个比特位解析也就是 0000 0001 0000 0001;输出结果就是257。
sizeof查看占用内存
typedef struct
{
unsigned int a:64;
unsigned int b:16;
}TestA;
typedef struct
{
unsigned int a:1;
unsigned int b:1;
}TestB;
int main(int argc, char *argv[])
{
printf("TestA size = %d\nTestB size = %d\n",sizeof(TestA),sizeof(TestB)); //输出为TestA size = 16 TestB size = 4
}
通过上面可以看出TestB占用的就是一个int占用的4字节,TestA占用的是两个int占用的8字节,可以看出TestA中的变量a实际占用空间就是8字节,b占用2字节,结构体对齐原则必须是最大成员的整数倍也就是必须是8的整数倍所以TestA是4字节,TestB是16字节。结构体对齐规则不懂的可以查看我另一篇博客:
C语言结构体,共用体占用内存原理解析
总结
在结构体中使用位域限制结构体成员所占的内存空间,位域限制生效范围为 1到变量成员类型所占内存大小个比特位,小于1编译会出现错误,大于变量成员类型所占内存大小个比特位会失效相当于没有设置位域限制。
边栏推荐
- 【分享】二层交换和三层交换转发
- MATLAB数字图像处理 实验二:单像素空域图像增强
- JVM architecture resolution
- Best practice path for problem solving
- 【今天的小go同学要去丢垃圾(1)】
- [bioinformation] protein interaction project ideas Growth Camp (14 days)
- Apple商业网站封锁Firefox浏览器
- module ‘urllib‘ has no attribute ‘urlretrieve‘
- js自写一个适用于object对象的forEach方法
- Intel x datawhale joint certification release!
猜你喜欢

Upgrade mysql5.5.27 to 5.7.35 under Windows Environment

Oppo and Yijia will be banned in Germany? It turned out to be targeted by "patent hooligan" Nokia!

“光”看新华三就够了: 园区如何进行全光技术选型-下篇

历史上的今天:Mozilla 基金会正式成立;Enigma 密码机的首次工作;任天堂推出 FC 游戏机...
![[today's little go is going to throw away the garbage (3)]](/img/d4/52ec88d9566ffff3d10f31a489fbbd.png)
[today's little go is going to throw away the garbage (3)]

Aardio - 【库】图形化的分页组件库

JMeter如何使用MD5加密并且对body进行指纹签名

捐赠 200 亿美元,比尔·盖茨势要退出世界富豪榜!

@ConditionalOnProperty的简单理解与使用

Unity 基础 之 Camera摄像机属性介绍
随机推荐
解决问题的最佳实践路径
Selenium八大元素定位及相对定位器
AC管理
js中finally的使用
The professional standard of the new profession "database operation administrator" was launched and developed
《經濟日報》點贊RPA領軍企業弘璣,助力金融機構數字化轉型
Apple商业网站封锁Firefox浏览器
安装无线网卡驱动
PGSQL中的limit n在sql语句中的位置
工业级知识图谱de构建与应用(二):商品知识的表示和建模
JVM architecture resolution
The bottom implementation of block
在线SQL转YAML工具
kotlin类和接口
关于网络时间协议(NTP)mod-6扫描漏洞处理
cv2.resize的坑
考研人暑期行为大赏top5
One stop Devops platform makes a big difference in development
我的创作纪念日
Unity 基础 之 Camera摄像机属性介绍