初识C语言中的位域

2018-05-09  本文已影响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位,所以爆炸了!~)

上一篇下一篇

猜你喜欢

热点阅读