一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第12天,点击查看活动详情。
大家好,我是芒果,一名非科班的在校大学生。对C/C++、数据结构、Linux及MySql、算法等领域感兴趣,喜欢将所学知识写成博客记录下来。 希望该文章对你有所帮助!如果有错误请大佬们指正!共同学习交流
作者简介:
- CSDN C/C++领域新星创作者blog.csdn.net/chuxinchang…
- 掘金LV3用户 juejin.cn/user/138142…
- 阿里云社区专家博主,星级博主,技术博主 developer.aliyun.com/profile/exp…
- 华为云云享专家 bbs.huaweicloud.com/community/m…
位段
什么是位段
位段的声明和结构是类似的,但是有两点不相同
-
1.位段的成员必须是int unsigned int(size_t),signed int,char (即为整形家族的类型)
-
2. 位段的成员名后面有一个冒号和一个数字(表示占多少比特位)
如:
struct A
{
int a:2;
int b:5;
int c:10;
int d:30;
};
//此时A就是一个位段类型
int main()
{
printf("%d\n",sizeof(struct A));//8
}
为什么位段类型A的大小为8?
位段的位:二进制位
2+5+10+30 = 47bit ->6byte即可保存,为什么要8byte呢?
我们要知道位段的内存分配!
位段的内存分配
- 1.位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型
-
- 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。
-
- 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。
int类型一次开辟4个字节,不够保存下一个成员则再开4个字节,char类型一次开辟1个字节,不够保存下一个成员则再开辟1个字节
所以上述:
struct A
{
int a:2;
int b:5;
int c:10;
int d:30;
};
举例子:
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;
}
//空间是如何开辟的?
假设从左到右使用空间,剩下的空间不够保存下一个成员,则再开辟下一个空间
此时对应的16进制位:620304
验证:
初始化:
s只占3个字节
赋值后:
对应16进制结果确实为 :620304
VS下位段内存空间存放规则:
- 从右边向左边使用空间,但如果左边空间不够保存下一个成员,则再开辟下一个空间,原来的空间浪费掉
位段不可以使用offsetof()计算位段成员与起始位置的偏移量
位段的跨平台性
- 1.int位段被当成有符号数还是无符号数是不确定的
- 2.位段中最大位的数目不能确定(16位机器最大16,2位机器最大32)
struct A
{
int a :2;
int b:5;
int c :30; //err
};
//16位机器, int占2个字节-16位
//c要占位30 > 16,错误
- 位段中的成员在内存中从左向右分配还是从右向左分配尚未定义
- 当一个结构包含两个位段,第二个位段成员所占位比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,是不确定的
总结:
跟结构体相比,位段同样达到同样的效果,但是可以很好的节省空间,但是又跨平台问题
位段的应用
枚举比结构体更节省空间