初识C语言中的位域
说实话以前在阅读《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位,所以爆炸了!~)