• c语言之位域


    位域的概念

    数据在存储的时候,并不需要占用一个完整的单元,只需要占用一个或者几个二进制位,限定数据的位数,节约内存资源

     简单来说就是,比如一个int,一般来说占用四个字节,那么四个字节就是32个位,但是我们实际当中用到的数据用不了那么多位,比如我们要存储月份,那么月份是不是就是1-12呢,那么我们这个时候就可以把这个int类型设计成四个位,那么它能存储最大的数据就是1111,对吗,也就是0-15的范围,存储2^4个数据,那么这个范围就是我们想要的合理范围。

    在c语言中,位域一般用于结构体里面

    话不多说,直接上代码

    1. #include
    2. #include
    3. struct Data
    4. {
    5. unsigned int num1 : 1;//1个位 ,二进制为1,也就是只能表示0或者1
    6. unsigned int num2 : 2;//2个位,二进制为00或者11 0->3
    7. unsigned int num3 : 3;//3个位 000 111 0->7
    8. };
    9. void main()
    10. {
    11. printf("%d\n", sizeof(struct Data));
    12. system("pause");
    13. }

    运行结果:

    后面再来说说怎么计算位域结构体的大小,再说一点就是,位域就相当于是限制了数据大小,不可越界,比如下面的代码

    1. #include
    2. #include
    3. struct Data
    4. {
    5. unsigned int num1 : 1;//1个位 ,二进制为1,也就是只能表示0或者1
    6. unsigned int num2 : 2;//2个位,二进制为00或者11 0->3
    7. unsigned int num3 : 3;//3个位 000 111 0->7
    8. };
    9. void main()
    10. {
    11. struct Data data1;
    12. data1.num1 = 2;
    13. printf("%d\n", data1.num1);
    14. system("pause");
    15. }

     上面会打印结果:

    一旦越界就不会打印我们想要的结果。

    如何判断带有位域的结构体大小

    1. #include
    2. #include
    3. union MyUnion1
    4. {
    5. char bj[5];//5
    6. int num;
    7. };
    8. union MyUnion2
    9. {
    10. char bj[5];
    11. int num[2];
    12. };
    13. struct stu
    14. {
    15. //联合体的大小就是占用最大的数据类型大小,但必须被最宽基本类型整除
    16. union{
    17. char bj[5];
    18. int bh[2];//
    19. }class;//8个字节//0 8
    20. char xm[8];//8 8
    21. float cj;//16 4
    22. };//16 + 4 = 20
    23. //这里按照结构体字节对齐来考虑
    24. struct test
    25. {
    26. char f1 : 3;//0 1
    27. short f2 : 4;//2 2
    28. char f3 : 5;//4 1
    29. };//5->6 才是short的整数倍
    30. struct test1
    31. {
    32. //同类型可以重合
    33. char num1 : 6;
    34. char num2 : 3;
    35. //上面占2个字节
    36. //下面重合占了四个字节
    37. int num3 : 5;
    38. int num5 : 20;//2-》4 + 4 = 8
    39. };//8
    40. struct test2{
    41. char f1 : 3;//0 1
    42. char f2;//非位域字段1 1//不用考虑重合
    43. char f3 : 5;//2 1 ->3
    44. };//3
    45. int main() {
    46. printf("%d\n", sizeof(struct test));
    47. printf("%d\n", sizeof(struct test1));
    48. printf("%d\n",sizeof(struct test2));
    49. getchar();
    50. return 0;
    51. }

    运行结果:

    如何用位域来读取一个整数、浮点数的二进制位

    1.先来看读取一个整数

    1. #include
    2. #include
    3. struct bit
    4. {
    5. unsigned char ch1 : 1;
    6. unsigned char ch2 : 1;
    7. unsigned char ch3 : 1;
    8. unsigned char ch4 : 1;
    9. unsigned char ch5 : 1;
    10. unsigned char ch6 : 1;
    11. unsigned char ch7 : 1;
    12. unsigned char ch8 : 1;
    13. };//数据类型相同占用重合1个字节,刚好八个位
    14. void main()
    15. {
    16. int num = 2;
    17. struct bit *p = #//指向int类型的首地址
    18. int length = 4;//int占四个字节,也就是4
    19. //4 3 2 1
    20. while (length--) {
    21. //注意,数据从右往左解析的
    22. printf("%d%d%d%d %d%d%d%d ",
    23. (p + length)->ch8,
    24. (p + length)->ch7,
    25. (p + length)->ch6,
    26. (p + length)->ch5,
    27. (p + length)->ch4,
    28. (p + length)->ch3,
    29. (p + length)->ch2,
    30. (p + length)->ch1);
    31. }
    32. system("pause");
    33. }

    运行结果

     2.再来看一个浮点数的读取

    1. #include
    2. #include
    3. struct bit
    4. {
    5. unsigned char ch1 : 1;
    6. unsigned char ch2 : 1;
    7. unsigned char ch3 : 1;
    8. unsigned char ch4 : 1;
    9. unsigned char ch5 : 1;
    10. unsigned char ch6 : 1;
    11. unsigned char ch7 : 1;
    12. unsigned char ch8 : 1;
    13. };//数据类型相同占用重合1个字节,刚好八个位
    14. void main()
    15. {
    16. float num = 19.625f;
    17. struct bit *p = #//指向int类型的首地址
    18. int length = 4;
    19. //4 3 2 1
    20. while (length--) {
    21. printf("%d%d%d%d %d%d%d%d ",
    22. (p + length)->ch8,
    23. (p + length)->ch7,
    24. (p + length)->ch6,
    25. (p + length)->ch5,
    26. (p + length)->ch4,
    27. (p + length)->ch3,
    28. (p + length)->ch2,
    29. (p + length)->ch1);
    30. }
    31. printf("%p\n", p);
    32. system("pause");
    33. }

    运行结果:

    看一下浮点数内存图 

     

     

  • 相关阅读:
    掌握Java核心知识,轻松应对面试挑战!
    ElementUI浅尝辄止30:PageHeader 页头
    以detectron2了解maskrcnn实现源码(0)--开篇
    常用注解@JsonField、@JsonFormat、@DateTimeFormat区别
    老卫带你学---leetcode刷题(399. 除法求值)
    61 不同路径
    SQLite库使用小结
    多线程知识-13
    基于Hardhat和Openzeppelin开发可升级合约(一)
    又推出两款纯净工具,360终于良心了?
  • 原文地址:https://blog.csdn.net/Pxx520Tangtian/article/details/125987494