所谓位段就是以位为单位定义长度的结构体类型的成员。
例如:
struct Demo
{
unsigned int a:2;
signed int b:2;
unsigned int c:4;
}demo;
Demo一共占用了8位,即一个字节长度。如果对其进行赋值,如:
demo.a = 4;
demo.b = 3;
demo.c = 2;
则打印结果会是 a 0(a两位最大为3,即11);b -1(含符号位);c 2;
定义字段,可以节省许多很多空间,试想,如果有一棋盘坐标需要进行定义,那么应该有坐标是否为空,棋盘棋子类别,棋盘各个方向的权值记录。。。由此,我们可定义以下数据结构:
struct ZuoBao
{
char qizi; //'0' 空, '1' 类型一','2' 类型2...
int rr0;
int rr1;
int rr2;
int rr3;
};
这样累计一下应该是20字节(其中char有三个字节用于对齐);
如果定义位段:
struct ZuoBao
{
unsigned qizi:5; //'0' 空, '1' 类型一','2' 类型2...
unsigned rr:10; //前两位为权值方向,后8位为权值(0----2^8-1)
};
此时这用了15位,4个字节(其实这个unsigned还有好多余地);
其实还有很多用例,比如说TCP协议头部结构,简单聊天程序信息等。。。
前面提到对齐,我对此了解不多。之所以出现这种情况是因为在读数时通常都是读取偶数地址,对于奇数的尽量跳过,一方面一些平台却是从偶数读起,另一方面就是从奇数读起,可能要跨度两次。如果存储单位有int,有short时,为了读取的快速,通常都是以最大(4字节)为一个存储。如以下例子:
struct Demo
{
short c;
int a;
char b;
}demo;
最大的单位为4字节,那么就有c用两个,空两个;a 用四个; b 用一个,空三个
共计12个字节。
当然,如果是
struct Demo
{
int a;
short c;
char b;
}demo;
a 用四个;c和b联合用四个;
共计8个字节。
struct Demo
{
int a;
short c;
char b;
char d;
}demo;
如果多个char(1个字节),这是d和c,d正好用4个,
共计8个。
struct Demo
{
int a;
short c;
short b;
char d;
}demo;
如果b变为short,这是就多出1个字节,没办法,它要在后面空出三个地址来;
此时共计12个字节。
位段对齐也可以自己设置,
#pragama pack(n) 就是定义了位段对齐的方式,编译器默认情况是4,如果定义n的话,编译器就会以n进行对齐,知道遇到#pragama pack()结束,恢复默认。
eg:
#pragma pack (2)
/* 2个字节的对齐方式 */
#pragma pack () /* 恢复编译器默认的对齐方式,即#pragma pack (4) */
以上是我对位段和对齐的理解,希望大家多多纠错,共同进步!