美文网首页
初识C语言中的位域

初识C语言中的位域

作者: 王伯卿 | 来源:发表于2018-05-09 21:15 被阅读0次

    说实话以前在阅读《C Primer Plus》的时候,似乎没有接触到位域,也可能是日久记忆些许有些模糊,但是今天在阅读w3c上的C语言教程的时候,觉得非常陌生。因此阅读了教程,试着写一篇笔记。

    首先应该是放上原帖的地址。C位域_w3c

    在开始实例之前,我们需要知道:

    1字节 = 8位

    如果您是32位的编译器,当您声明一个int变量的时候,计算机将会使用32位即4个字节来存储这个变量。而接下来出现的无符号unsigned int也是占4个字节。让我们看下面这个实例。

    #include <stdio.h>
    
    struct{
        unsigned int widthValidated;
        unsigned int heightValidated;
    }status1;
    
    int main(void){
        printf("Memory size occupied by status1 is : %d.\n",sizeof(status1));
        getchar();
        return 0;
    }
    

    最后控制台输出:

    Memory size occupied by status1 is : 8.
    

    我是64位的编译器,因此这个结构体总共占用了64位,即8个字节的大小。
    但是,有的时候,在实际的使用中,当我们只想使用true或者false的真假值时,我们便不需要那么多的空间去存储这个变量,因为我们只需要0和1两个数字。因此我们有了位域这个概念,位域或者位段,故名思意就是位置区域,我们将会通过定义一个位域来告诉计算机,一个1位的二进制中存储的位置。
    位域的定义方法与结构体相似,如下:

    struct
    {
      type [member_name] : width ;
    };
    

    让我们来试着使用位域,并且测试一下位域的大小吧。

    #include <stdio.h>
    
    struct{
        unsigned int widthValidated;
        unsigned int heightValidated;
    }status1;
    
    struct{
        unsigned int widthValidated : 1;
        unsigned int heightValidated : 1;
    }status2;
    
    int main(void){
        printf("Memory size occupied by status1 is : %d.\n",sizeof(status1));
        printf("Memory size occupied by status2 is : %d.\n",sizeof(status2));
        getchar();
        return 0;
    }
    

    最后控制台输出:

    Memory size occupied by status1 is : 8.
    Memory size occupied by status2 is : 4.
    

    这里就非常清晰,status1占用了8个字节,而status2占用了4个字节。但是虽然status2占用了4个字节,但是只有2位是用来存储的。当我们使用32个变量时,status2将会使用4个字节来存储,但是当我们使用了33个变量,即超出一个的时候,status2即会启用8个字节来存储那一个多出来的变量。我们可以试试。

    #include <stdio.h>
    
    struct{
        unsigned int widthValidated;
        unsigned int heightValidated;
    }status1;
    
    struct{
        unsigned int widthValidated_1 : 1;
        unsigned int widthValidated_2 : 1;
        unsigned int widthValidated_3 : 1;
        unsigned int widthValidated_4 : 1;
        unsigned int widthValidated_5 : 1;
        unsigned int widthValidated_6 : 1;
        unsigned int widthValidated_7 : 1;
        unsigned int widthValidated_8 : 1;
        unsigned int widthValidated_9 : 1;
        unsigned int widthValidated_10 : 1;
        unsigned int widthValidated_11 : 1;
        unsigned int widthValidated_12 : 1;
        unsigned int widthValidated_13 : 1;
        unsigned int widthValidated_14 : 1;
        unsigned int widthValidated_15 : 1;
        unsigned int widthValidated_16 : 1;
        unsigned int widthValidated_17 : 1;
        unsigned int widthValidated_18 : 1;
        unsigned int widthValidated_19 : 1;
        unsigned int widthValidated_20 : 1;
        unsigned int widthValidated_21 : 1;
        unsigned int widthValidated_22 : 1;
        unsigned int widthValidated_23 : 1;
        unsigned int widthValidated_24 : 1;
        unsigned int widthValidated_25 : 1;
        unsigned int widthValidated_26 : 1;
        unsigned int widthValidated_27 : 1;
        unsigned int widthValidated_28 : 1;
        unsigned int widthValidated_29 : 1;
        unsigned int widthValidated_30 : 1;
        unsigned int widthValidated_31 : 1;
        unsigned int widthValidated_32 : 1;
    }status2;
    
    int main(void){
        printf("Memory size occupied by status1 is : %d.\n",sizeof(status1));
        printf("Memory size occupied by status2 is : %d.\n",sizeof(status2));
        getchar();
        return 0;
    }
    

    这个时候status2仍然只占用4个字节。
    当我们增加到33个变量的时候,sizeof将会返回8个字节。

    带有预定义宽度的变量被称为位域。位域可以存储多于 1 位的数,例如,需要一个变量来存储从 0 到 7 的值,您可以定义一个宽度为 3 位的位域,如下:

    struct
    {
      unsigned int age : 3;
    } Age;
    

    上面的结构定义指示 C 编译器,age 变量将只使用 3 位来存储这个值,如果您试图使用超过 3 位,则无法完成。让我们来看下面的实例:

    #include <stdio.h>
    #include <string.h>
    
    struct
    {
      unsigned int age : 3;
    } Age;
    
    int main( )
    {
       Age.age = 4;
       printf( "Sizeof( Age ) : %d\n", sizeof(Age) );
       printf( "Age.age : %d\n", Age.age );
    
       Age.age = 7;
       printf( "Age.age : %d\n", Age.age );
    
       Age.age = 8;
       printf( "Age.age : %d\n", Age.age );
    
       return 0;
    }
    

    当上面的代码被编译时,它会带有警告,当上面的代码被执行时,它会产生下列结果:

    Sizeof( Age ) : 4
    Age.age : 4
    Age.age : 7
    Age.age : 0
    

    首先定义age存储3位。下面看一下对应的数字的二进制,更加清晰明了:
    4——100
    5——101
    6——110
    7——111
    8——1000(age只能存储3位,所以爆炸了!~)

    相关文章

      网友评论

          本文标题:初识C语言中的位域

          本文链接:https://www.haomeiwen.com/subject/upiorftx.html