有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示
1)
#include <string.h>
#include <stdio.h>
#include <memory.h>
typedef struct AA
{
int b1:5;
int b2:2;
}AA;
void main()
{
AA aa;
char cc[100];
strcpy(cc,"0123456789abcdefghijklmnopqrstuvwxyz");
memcpy(&aa,cc,sizeof(AA));
printf("%d/n",aa.b1);
printf("%d/n",aa.b2);
}
首先sizeof(AA)的大小为4,b1和b2分别占5bit和2bit.
经过strcpy和memcpy后,aa的4个字节所存放的值是:
0,1,2,3的ASC码,即00110000,00110001,00110010,00110011
所以,最后一步:显示的是这4个字节的前5位,和之后的2位
分别为:10000,和01
因为int是有正负之分 所以:答案是-16和1
2)定义一个结构体,一共有16位,变量a(0-3位),变量b(8-11位),变量c(12-15位)。
一共两种方法:
struct bs
{
unsigned a:4
unsigned :0 /*空域*/
unsigned b:4 /*从下一单元开始存放*/
unsigned c:4
}
struct bs
{
unsigned a:4
unsigned :4 /*空出4位*/
unsigned b:4
unsigned c:4
}
3)
#pragma pack(1)
struct A
{
char t:4;
char k:4;
unsigned short i:8;
//unsigned short j:8;
}
sizeof(A)
把注释去掉和不去掉都是一样的,答案是3,这样可以看出虽然没有按大家一般关注的内存边界对齐(我已经设为1字节对齐了),而是按照的类型边界对齐的。
也就是说如果你定义的是short,不管用了几位它都会把剩下的位用完。
short两字节,16位,虽然没有用剩下8位,但算所占空间的时候都要算进去。
struct A
{
char t:4;
unsigned short i:8;
char k:4;
}这个列子更明显了。
#pragma pack(4)
struct A
{
char t:4;
unsigned short i:8;
char k:4;
}结果是6
当前最大的类型是short占用2个字节
虽然是按四个字节对齐,但是仍然t占2字节,i占两字节,k占两字节
struct s1
{
int i: 8;
int j: 4;
int a: 3;
double b;
};
struct s2
{
int i: 8;
int j: 4;
double b;
int a:3;
};
printf("sizeof(s1)= %d/n", sizeof(s1));
printf("sizeof(s2)= %d/n", sizeof(s2));
16, 24
这个跟刚才的很像,只是说s1先把int占满后才开辟b;
请不要回“仔细看看”这种留言了。