位域全解析
2009-09-14 00:33 Logic0 阅读(5602) 评论(0) 编辑 收藏 举报 所谓”位域“是把一个字节中的二进位划分为几
个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。
它实际上是C语言提供的一种数据结构。
使用位域的好处是:
1.有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。这样节省存储空间,而且处理简便。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。
2.可以很方便的利用位域把一个变量给按位分解。比如只需要4个大小在0到3的随即数,就可以只rand()一次,然后每个位域取2个二进制位即可,省时省空间。
由于没有其他硬件平台实验条件,所以下边的例子基于intel x86硬件平台,内存排列为高位到低位,有SUN SPARC或其他平台的兄弟可以自行实验下。
位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:
struct
{
unsigned char x1:2;
unsigned char x2:2;
unsigned char x3:2;
unsigned char x4:2;
} wy;
这个位域定义的意思是,结构体内有四个变量x1,x2,x3,x4,每个变量占2个二进制位,那你猜猜这个结构体占大多空间呢?是1个字节,因为共8个二进制位,也就是1个字节。这个可以自己sizeof()一下进行验证。是不是节省了空间呢。
那么来看下一个例子,实现的是上述位域的作用2
union wy
{
struct
{
unsigned char x1:2;
unsigned char x2:2;
unsigned char x3:2;
unsigned char x4:2;
}cn;
unsigned char s;
} tmp;
看程序:
#include "stdio.h"
union wy
{
struct
{
unsigned char x1:2;
unsigned char x2:2;
unsigned char x3:2;
unsigned char x4:2;
}cn;
unsigned char s;
} tmp;
int main()
{
tmp.s = 174; //二进制形式是10101110
printf("tmp.s is %d\n",tmp.s);
printf("x1 is %d\n",tmp.cn.x1);
printf("x2 is %d\n",tmp.cn.x2);
printf("x3 is %d\n",tmp.cn.x3);
printf("x4 is %d\n",tmp.cn.x4);
return 0;
}
输出的结果是2,3,2,2。
从这个结果我们就可以看出来,这个按位分解是从地位到高位的。对照表:
x4 x3 x2 x1
10 10 11 10
高位<----地位
但是有一点必须注意的是,这是在1个字节内的分配,如果涉及到跨字节的位域,则要进行另外的处理。这个问题我们稍后讨论。
它实际上是C语言提供的一种数据结构。
使用位域的好处是:
1.有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。这样节省存储空间,而且处理简便。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。
2.可以很方便的利用位域把一个变量给按位分解。比如只需要4个大小在0到3的随即数,就可以只rand()一次,然后每个位域取2个二进制位即可,省时省空间。
由于没有其他硬件平台实验条件,所以下边的例子基于intel x86硬件平台,内存排列为高位到低位,有SUN SPARC或其他平台的兄弟可以自行实验下。
位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:
struct 位域结构名
{ 位域列表 };
其中位域列表的形式为: 类型说明符 位域名:位域长度;
下面先看一个例子{ 位域列表 };
其中位域列表的形式为: 类型说明符 位域名:位域长度;
struct
{
unsigned char x1:2;
unsigned char x2:2;
unsigned char x3:2;
unsigned char x4:2;
} wy;
这个位域定义的意思是,结构体内有四个变量x1,x2,x3,x4,每个变量占2个二进制位,那你猜猜这个结构体占大多空间呢?是1个字节,因为共8个二进制位,也就是1个字节。这个可以自己sizeof()一下进行验证。是不是节省了空间呢。
那么来看下一个例子,实现的是上述位域的作用2
union wy
{
struct
{
unsigned char x1:2;
unsigned char x2:2;
unsigned char x3:2;
unsigned char x4:2;
}cn;
unsigned char s;
} tmp;
union是联合,联合的好处就是里边的所有变量都用的是一个内存空间,不理解的参见谷歌。
也就是说s和结构体cn用的是一个内存空间,都是1个字节。这样就可以把s给按位分解。这个时候不知道你想没有想这样一个问题,按位分解,如何分解,从高位到低位还是从低位到高位,下边我们通过实验来得出结论。看程序:
#include "stdio.h"
union wy
{
struct
{
unsigned char x1:2;
unsigned char x2:2;
unsigned char x3:2;
unsigned char x4:2;
}cn;
unsigned char s;
} tmp;
int main()
{
tmp.s = 174; //二进制形式是10101110
printf("tmp.s is %d\n",tmp.s);
printf("x1 is %d\n",tmp.cn.x1);
printf("x2 is %d\n",tmp.cn.x2);
printf("x3 is %d\n",tmp.cn.x3);
printf("x4 is %d\n",tmp.cn.x4);
return 0;
}
输出的结果是2,3,2,2。
从这个结果我们就可以看出来,这个按位分解是从地位到高位的。对照表:
x4 x3 x2 x1
10 10 11 10
高位<----地位
但是有一点必须注意的是,这是在1个字节内的分配,如果涉及到跨字节的位域,则要进行另外的处理。这个问题我们稍后讨论。