union的0x3个妙用(I)

本文介绍了嵌入式系统中使用union结构的两种实用技巧,包括如何通过union判断CPU的字节序(Little-endian或Big-endian),以及如何利用union进行高效的数据存储管理。
在嵌入式系统中,一般不建议使用union结构,因为union结构中的各个成员之间存在相互影响,容易滋生问题。可见,union也是把双刃剑。懂得使用它的人可以做到“削铁如泥”,而不懂得使用它的人很可能会被其所伤。下面介绍的几种方法都是嵌入式系统常用的几种技巧。如果熟练掌握,将来定有所用。

1.all的使用

使用all的数据结构模型:

typedef _my_union
{
unsigned int all;

/*sizeof(my_union.my_struct)必须与sizeof(my_union.all)相等*/
struct
{
...
}my_struct;

}my_union;


----------EXAMPLE 1--------

  嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。例如,32bit宽的数 0x12345678在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址 存放内容
0x4000 0x78
0x4001 0x56
0x4002 0x34
0x4003 0x12
  而在Big-endian模式CPU内存中的存放方式则为:
内存地址 存放内容
0x4000 0x12
0x4001 0x34
0x4002 0x56
0x4003 0x78

  联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性就可以轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写。

测试代码:                                   

int isLittleEndian()
{
union _dword
{
int all;

struct _bytes
{
char byte0;/*对little来说是最低位,而对big则是最高位*/
char pad[3];
}bytes;

}dword;

dword.all=0x87654321;/*all的功能就是给dword四个字节赋值*/

return (0x21==dword.bytes.byte0);/*查看第一个字节*/
}

分析:                                     如果你的处理器调用函数isLittleEndian返回1,那么说明你的处理器为little endian,否则为big endian.注意,如果在little endian处理器上,byte0和pad按内存从低到高的存放顺序:LOW->byte0 pad[0] pad[1] pad[2] ->HIGH;0x87654321按内存从低到高的存放顺序: 0x21 0x43 0x65 0x87, 可见byte0对应到0x21。所以通过判断dword中第一个字节dword.bytes.byte0是否与0x21相等就可以看出是否是little endian。
----------EXAMPLE 2--------
#include <stdio.h>
typedef union _student
{
unsigned int all;/*all可以同时清理或设置info中的所有内容*/

struct
{
unsigned int pad: 7;
unsigned int used: 1;/*高位*/
unsigned int personal_id: 8;
unsigned int class_id: 3;
unsigned int subject_id: 6;
unsigned int score: 7;/*低位*/
}info;

}student;
#define MAX_STUDENT_NUM 100
unsigned int students;
unsigned int student_database[MAX_STUDENT_NUM]={0};

int add_to_database(unsigned int data);
int find_from_database(unsigned int personal_id);
int delete_from_database(unsigned int personal_id);
void print_database(void);
void print_student(unsigned int data);

int add_to_database(unsigned int data)
{
student stu;
int i;

for(i=0;i<MAX_STUDENT_NUM;i++)
{
stu.all = student_database[i];

if(!stu.info.used)
{
stu.all = data;
stu.info.used = 1;

student_database[i] = stu.all;
return 1;
}
}

return 0;
}


int find_from_database(unsigned int personal_id)
{
student stu;
int i;

for(i=0;i<MAX_STUDENT_NUM;i++)
{
stu.all = student_database[i];

if(stu.info.used && stu.info.personal_id==personal_id)
{
return stu.all;
}
}

return -1;
}

void print_student(unsigned int data)
{
student stu;

stu.all = data;

printf("personal id %d,class id %d,subject id %d,score %d\n",
stu.info.personal_id,stu.info.class_id,stu.info.subject_id,
    stu.info.score);
}


void print_database(void)
{
student stu;
int i;

for(i=0;i<MAX_STUDENT_NUM;i++)
{
stu.all = student_database[i];

if(stu.info.used)
{
print_student(stu.all);
}
}
}

int main(int argc, char *argv[])
{
student jack,jone;

jack.all = 0;

jack.info.personal_id = 102;
jack.info.class_id = 2; /*class 2*/
jack.info.subject_id = 2; /*English*/
jack.info.score = 50; /*fouled*/
add_to_database(jack.all);
jone.all = 0;

jone.info.personal_id = 88;
jone.info.class_id = 2; /*calss 2*/
jone.info.subject_id = 2; /*English*/
jone.info.score = 73; /*passed*/

add_to_database(jone.all);

jack.all = find_from_database(jack.info.personal_id);

if(jack.all<0)
{
printf("no such student with id %d\n",jone.info.personal_id);
}
else
{
printf("found! ");
print_student(jack.all);
}

print_database();
}

运行结果:
found! personal id 102,class id 2,subject id 2,score 50
personal id 102,class id 2,subject id 2,score 50
personal id 88,class id 2,subject id 2,score 73
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值