位域是C/C++中常用的数据结构。 在某些情况下合理的使用位域可以节省存储空间,提高运行效率并提高程序的可读行。
按照我以往的编程经验来看,通常以下情况下会优先考虑使用位域。1)有很多的状态标记,需要集中存储,比如tcp链接
的状态 2)协议栈相关的数据结构,尤其是底层通信协议中很多情况使用一个或者几个bit来表示某种状态,数据长度等等。
这时候就会使用到位域。
struct SNField{
unsigned char seq:7 ; // frame sequnce
unsigned char startbit:1 ; // indicate if it's starting frame 1 for yes.
};
struct STField{
unsigned int flag_tt:20 ; // frame sequnce
unsigned int flag_ee:12 ; // indicate if it's starting frame 1 for yes.
};
这里要注意的位域为单位的成员和其他的struct的成员, 都是按照从低地址到高地址的方式分配内存的。
这里seq 按照内存地址从低到高分配,获得0~6个bit. 而startbit获得最高位内存的1个bit. 所以位域完全是从内存地址解释每一个bit。
注意位域与联合的区别,前两天刚犯的一个错误拿出来自省一下。 在解析某个协议字段,低0~7bit, 是序列号,最高的1个bit说明是否是
开始帧。 我想赋值的时候直接以byte赋值,而在解析的时候才按照bit去解析。 这样赋值操作就会很简单,因为从网络读出来数据也是按照
字节流接收的。感觉应该是用一个联合union, 于是呼有了如下的结构
union SNFlag{
unsigned char seq:7 ; // frame sequnce, N-1 ~ 0, N is the num of fame, N-1 is the first, 0 means the last.
unsigned char startbit:1 ; // indicate if it's starting frame 1 for yes.
unsigned char flag;
};
然后给flag赋值 0x80,
all is 128
seq 7 is 0
startbit 1 bit is 0
然后给flag赋值 0x81,
all is 129
seq 7 is 1
startbit 1 bit is 1
然后给flag赋值 0x82,
all is 129
seq 7 is 2
startbit 1 bit is 0
发现没有,seq和 startbit 都是从第0个bit开始解析,而不是预想的startbit从第7个bit开始解析。重新查了一个union的定义
struct和union的重要区别:
struct为每个字段在不同的偏移处分配存储空间,而联合则将所有的字段重叠在内存中的相同偏移处。
所以一个union中所有的字段都是尝试在同一个地址,也就是低地址开始解释变量。
那么怎么办呢,可能您已经想到了。先把位域放在一个结构体中,然后和一个字节在放在联合体中。
struct SNField{
unsigned char seq:7 ; // fhe first, 0 means the last.
unsigned char startbit:1 ; // indicate if it's starting frame 1 for yes.
};
union SNFlag{
struct SNField snf;
unsigned char flag;
};
按照我以往的编程经验来看,通常以下情况下会优先考虑使用位域。1)有很多的状态标记,需要集中存储,比如tcp链接
的状态 2)协议栈相关的数据结构,尤其是底层通信协议中很多情况使用一个或者几个bit来表示某种状态,数据长度等等。
这时候就会使用到位域。
struct SNField{
unsigned char seq:7 ; // frame sequnce
unsigned char startbit:1 ; // indicate if it's starting frame 1 for yes.
};
struct STField{
unsigned int flag_tt:20 ; // frame sequnce
unsigned int flag_ee:12 ; // indicate if it's starting frame 1 for yes.
};
这里要注意的位域为单位的成员和其他的struct的成员, 都是按照从低地址到高地址的方式分配内存的。
这里seq 按照内存地址从低到高分配,获得0~6个bit. 而startbit获得最高位内存的1个bit. 所以位域完全是从内存地址解释每一个bit。
注意位域与联合的区别,前两天刚犯的一个错误拿出来自省一下。 在解析某个协议字段,低0~7bit, 是序列号,最高的1个bit说明是否是
开始帧。 我想赋值的时候直接以byte赋值,而在解析的时候才按照bit去解析。 这样赋值操作就会很简单,因为从网络读出来数据也是按照
字节流接收的。感觉应该是用一个联合union, 于是呼有了如下的结构
union SNFlag{
unsigned char seq:7 ; // frame sequnce, N-1 ~ 0, N is the num of fame, N-1 is the first, 0 means the last.
unsigned char startbit:1 ; // indicate if it's starting frame 1 for yes.
unsigned char flag;
};
然后给flag赋值 0x80,
all is 128
seq 7 is 0
startbit 1 bit is 0
然后给flag赋值 0x81,
all is 129
seq 7 is 1
startbit 1 bit is 1
然后给flag赋值 0x82,
all is 129
seq 7 is 2
startbit 1 bit is 0
发现没有,seq和 startbit 都是从第0个bit开始解析,而不是预想的startbit从第7个bit开始解析。重新查了一个union的定义
struct和union的重要区别:
struct为每个字段在不同的偏移处分配存储空间,而联合则将所有的字段重叠在内存中的相同偏移处。
所以一个union中所有的字段都是尝试在同一个地址,也就是低地址开始解释变量。
那么怎么办呢,可能您已经想到了。先把位域放在一个结构体中,然后和一个字节在放在联合体中。
struct SNField{
unsigned char seq:7 ; // fhe first, 0 means the last.
unsigned char startbit:1 ; // indicate if it's starting frame 1 for yes.
};
union SNFlag{
struct SNField snf;
unsigned char flag;
};