union的0x3个妙用(I)

在嵌入式系统中,一般不建议使用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开始存放)为:
内存地址存放内容
0x40000x78
0x40010x56
0x40020x34
0x40030x12
  而在Big-endian模式CPU内存中的存放方式则为:
内存地址存放内容
0x40000x12
0x40010x34
0x40020x56
0x40030x78

  联合体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
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值