我们在存储一些数据有时候并不需要一个完整字节,可能只需要使用几个bit位存储数据即可,所以为了节省内存空间,C语言提供“位段”的数据结构,可以把一个(或多个)字节分成几个不同位数(bit)区域,这样就可以把几个对象放到不同的区域然后用一个(或多个)字节来表示。
位段声明形式和定义结构体相似,但它的成员是一个或多个位的字段,其结构为:
struct 结构名
{
位段列表;
};
struct bit_sizeof { int a:2;//00 01 10 11 int b:3; int c:8; int d:30; };
其中位段列表形式如下,其中位段长度指的是某个成员变量所占用的二进制位数(bit):
类型说明符 位段名:位段长度
一个位段声明的例子1:
struct CHAR { unsigned ch : 7; unsigned font : 8; unsigned len : 9; }ch1;
上例中,每个成员变量位宽大小分别是7bit、8bit、9bit,使用sizeof()得出所占大小为4字节,因为是成员类型相同,所以后面的成员紧邻前一个成员存储,总共24bit,不满一个unsigned 类型长度,所以大小为4字节。
需要注意的是,位段的宽度不能超过它所依附的数据类型的长度,也就是说每个成员变量的类型都会有大小限制,如果“:”后面的数据超过了这个长度,运行后输出的该值可能出错,需要注意。另外,若成员的长度大于位段宽度则可能输出不完整,如下例2:
struct bs { unsigned char ch1 : 8; unsigned char ch2 : 6; //unsigned char ch3 : 9; //位段宽度超过数据类型宽度,gcc编译出错 }test;
1.当位段成员的类型相同时,位段成员会挨着存储,若存储后位段成员的bit位宽之和小于类型大小,则sizeof()该段位为类型大小,若位宽之和总大小大于类型大小,则sizeof()该段位大小为,则其偏移量为类型大小的整数倍。
该例中,位段成员位宽之和小于该类型大小,sizeof()该位段为4;
struct bs { int a: 1; int b: 2; int c: 3; } ;
该例中,位段成员位宽之和大于该类型大小,sizeof()该位段为8
2.当相位段员的类型不同时,不同系统环境sizeof()该段位可能会有不同的大小结果。
该例中,gcc下运行sizeof()该位段大小为4,表明三个位段成员会挨着存储;在vs2010下运行sizeof()该位段大小为8,表明前两个位段成员挨着存储,后一个位段成员与前两个成员类型不同,所以另起一个单元存储。
struct bs { int a : 1; int b : 4; char c : 4; } ;
#includevoid bit_size(void); int main() { bit_size(); return 0; } void bit_size(void) { struct bit_sizeof { int a:2;//00 01 10 11 int b:3; int c:8; int d:30; }; struct bit_sizeof bit_01; bit_01.a=3;//初始化 unsigned char *p=&bit_01;//字符型指针指向bit_01的首地址 printf("*p=%#pn",p);//地址位置 printf("*p=%un",*p); bit_01.b= 0x1E; printf("*p=%un",*p); }
运行结果:
作业1: 请编写一个程序将一个整型变量右移4位,并以二进制的形式输出移位前和移位后的数值,看看你的系统是补0还是补1?#includeint main() { int a; printf("请输入一个整数:n"); scanf("%d",&a); int c=a; unsigned int b = 0x1<<31; for(int i=1;i<=32;i++) { a & b? putchar('1') : putchar('0'); a <<= 1; if(i%8==0) printf(" "); } c >>= 4; printf("n"); for(int i=1;i<=32;i++) { c & b? putchar('1') : putchar('0'); c <<= 1; if(i%8==0) printf(" "); } return 0; }
由结果可知:本系统补0
作业2:无符号数左移移位相当于该数乘以2,编写一个函数,接收两个整型变量num和pow作为实参,被掉函数使用移位运算计算num*2^pow的结果。然后分别以整型和二进制形式输出。#includeint main() { int a,b; printf("请输入两个整数n"); scanf("%d %d",&a,&b); change(a,b); return 0; } void change(int x,int y) { int z=(x<<1)^y; printf("%dn",z); unsigned int b = 0x1<<31; for(int i=1;i<=32;i++) { z & b? putchar('1') : putchar('0'); z <<= 1; if(i%8==0) printf(" "); } }