C语言中位域定义: 以结构体中定义申明变量的形式: 类型说明符 位域名:位域宽度
struct bit{
int a:4; // 申明位域变量a,占用4个bit位宽度
int b:4; // 申明位域变量b,占用4个bit位宽度
int c:4; // 申明位域变量c,占用4个bit位宽度
};
在gcc编译器中对结构体进行了默认的对齐操作,以下的所有的现象都是基于gcc的编译条
件:
1):申明的两个相连的位域变量占位一般都是紧密连接的,例如上面的a和b,或者是b和
c:a占用起始字节的低4位,b占用起始字节的高4位,而c占用的是第二个字节的低4位,
依次紧密相连。
2):如果一个位域变量的占位数不超过1个字节,那么这个变量的占位分配是不会横跨两
个字节的,也就是说他必须在一个字节内,例如上面的b如果占位为5的话,如果直接按1
)说的那样他的占位分配就会横跨不同的字节,这种情况下应该从下一个字节开始分配;
如果位域变量的占位数超过了一个字节,那么占位分配不能直接在前一个变量后面接续,
而应从下一个字节开始占位;因此这段话的意思就是:如果一个位域变量的占位数超过了
上一个位域变量占位之后剩余的bit位(我说的是一个字节内的剩余),那么这个位域变
量应该从下一个"干净"的字节开始占位。所以我在 1) 中说的是一般。
3):整个结构体大小的确定方法:
实际上,整个结构体大小,并不是内部占了多少个bit位这个简单,本身编译器就会进行
一个字节对齐的操作,其次和普通的结构体字节对齐方式又大有不同:
如果我们连续申明的几个位域变量占位之和只要不超过这些变量中类型大小最大的那个类
型的大小,那么这些连续申明的变量总的大小就是这个类型的大小,例如:
struct bit{
int a:4;
int b:4;
char c:4;
char d:4;
}
根据上面的方法,这几个变量中类型最长就是int,而他们的bit位长度相加并不会超过
int类型的长度,所以这个结构体的大小就是4字节。如果超过了,例如下面这种情况:
struct bit{
int a:8;
int b:8;
int c:8;
char d:8;
char e:3;
};
那么这种情况就是: 前面的4个变量占位刚好就是int的大小,分为一组,而后面的e又
单独分为一组,也是按照上面的方法来确定这组的大小,这组中最大的类型就是char,而
e没有超过char的大小,所以就是1个字节,所以整个结构体的大小就是 4+1 = 5个字节。
3):我们可以在结构体中申明一个没有位域名的变量,例如:
struct bit{
int a:4;
int b:4;
int :0;
int :2;
};
那么此时这个没有名字的位域变量是不能被使用的,他只是被用来占位而已,如果是 占
位为0的无名位域变量,例如第3项,int :0,虽然也是占位,但是稍稍要复杂许多:
这个变量意思就是从一个新的字节开始分配新的变量,但是这个具体的新的字节是那个字
节,并不一定就是下一个字节,是跟具体的类型修饰符有关,如果是char修饰,那么就是
从下一个字节开始,看例子吧,我都不知道怎么表达了。
struct bit{
int a:8;
int b:8;
int :0; // 从a的起始开始数4个字节之后开始占位
};
struct bit{
int a:8;
int b:8;
char :0; // 从b的起始开始数1个字节之后开始占位
};
struct bit{
int a:8;
int b:8;
int c:8;
short :0; // 从b的起始开始数2个字节之后开始占位
};
struct bit{
int a:8;
int b:8;
int c:8;
int d:8;
int :0; // 从a的起始开始数4个字节之后开始占位
};
struct bit{
int a:8;
int b:8;
int c:8;
int d:8;
int e:8;
int :0; // 从e的起始开始数4个字节之后开始占位,因为此时前面4个已经成一组
了
};
struct bit{
int a:8;
int b:8;
int c:8;
int d:8;
int e:8;
short :0; // 从e的起始开始数2个字节之后开始占位,因为此时前面4个已经成一
组了
};
struct bit{
int a:8;
int b:8;
int c:8;
int d:8;
int e:8;
char :0; // 从e的起始开始数1个字节之后开始占位,因为此时前面4个已经成一
组了
};
一定要注意了:空开的空间也算是这个结构体的空间。