将几个 位段变量拼接放入一个16位中,为简便,我让每个字段的值等于它的位段长度。
struct PUD
{
unsigned int version :4; //协议版本,version 占用4bit
unsigned int Vendor_Code :4; //厂商代码,占用4bit
unsigned int frame_type:5; //帧类型, 占用5bit
unsigned int data_len:11; //信息段长度, 占用11bit
unsigned int crane_type:4; //塔吊类型, 占用4bit
unsigned int multi_pw:4; //倍率, 占用4bit
unsigned int Prot_Type :1; //保护类型, 占用1bit
unsigned int Prot_reserved :3; //保留字段,占用3bit
unsigned int Prot_e_num:4; //保护区元素个数, 占用4bit
unsigned int op_mark:1; //操作标志, 占用1bit
unsigned int op_reserved :2; //保留字段, 占用2bit
unsigned int incident :3; //本次事件, 占用3bit
};
struct PUD packet_data;
int test2;
packet_data.crane_type=4;
packet_data.multi_pw=4;
packet_data.Prot_Type=1;
packet_data.Prot_reserved=3;
packet_data.Prot_e_num=4;
test2=0x00; //清零
//从低位填充
test2=test2|packet_data.Prot_e_num;
test2=test2|packet_data.Prot_reserved<<4;
test2=test2|packet_data.Prot_Type<<7;
test2=test2|packet_data.multi_pw<<8;
test2=test2|packet_data.Prot_num<<12;
test2=test2;//test2赋值后没有调用,为了在IAR编译器给test2分配空间,能看到test2的值,加了这一句。
结果:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cGcq5SMzMGN4YGM2IDOxEmZhNzYlFTZzUTOllDNwUDNjFDN18CX5IzLclDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjL5M3Lc9CX6MHc0RHaiojIsJye.jpg)
#include <stdio.h>
typedef struct _A
{
unsigned a:4;//位段成员的类型仅能够为unsigned或者int
unsigned b:4;
unsigned c:2;
unsigned d:6;
unsigned E:1;
unsigned D:2;
unsigned T:3;
unsigned A:9;
unsigned h:4; //前面已经为31,故4+31>32已超过一个存储单元,所以4在一个新的存储单元存放
unsigned y:29;//由于前面的4在一个新的存储单元的开头存放,且29+4>32, 故在另一个新的存储单元存放
}A; //所以最后求出的A的大小是4 + 4 + 4 =12
typedef struct _S
unsigned a:4;
unsigned c:22;
unsigned q:1;
unsigned h:1;
//unsigned i:33; // 错误:‘i’ 的宽度超过它自身的类型
//unsigned i:1;当多出此行时,该结构体大小由4变为8,因为此行之前正好为32位
} S;
typedef struct _T
{ //当没有占满一个存储单元时,结构体的大小对齐为一个存储单元的大小
unsigned a:2;
unsigned b:2;
unsigned j:1;
unsigned : 1;//可以定义无名位段,此例中该无名位段占用1位的空间,该空间将不被使用
} T;
typedef struct _V
unsigned a:1;
unsigned :0; //定义长度为0的位段时不能指定名字,否则编译不过
unsigned d:1; //定义了0字段后,紧接着的下一个成员从下一个存储单元开始存放;
}V; //此例子中,d前面那个存储单元中的余下的27位中被0填充了
int main()