vlambda博客
学习文章列表

C语言位段的应用实例


C语言位段的应用实例




C语言位段的应用实例


今天是2月29日,只有闰年的2月才会有29天,自从不打游戏以后,发现自己的时间多了起来,尽管今天花了大半天去解决一个小问题,但是问题总算可以解决了不是吗,晚饭过后想想,四年才那么一次,不能错过啊,写一篇推文纪念一下。这篇推文是记录我之前遇到代码问题,以前总觉得自己好像每天都没有什么收获,但是事实上是缺少了记录,有时候花了很多时间去解决的问题不记录下来转头就忘记了,真是浪费。




我在做一个单片机的项目的时候用到一个模块,这个模块是通过串口通信的,模块有这么一条数据规定:unsigned char的低3位和高5位分别存放不同的指令信息,我马上就想到了位段操作,写了如下代码:


#include <stdio.h>struct commandparameter_t{ unsigned char  codeformat:3;  unsigned char backgroundmusic:5;};
int main(void){   unsigned char *para;  struct commandparameter_t test;  test.backgroundmusic = 0x0a;  test.codeformat = 0x01;          para = (unsigned char*)&test;          printf("%x", *para);      getchar();      return 0;}

解析
C语言位段的应用实例





什么是大小端模式呢?

解析
C语言位段的应用实例





如何区分编译器或者操作系统的大小端模式呢?

专家解答
C语言位段的应用实例

判断的原理很简单,char占1个字节,int占4个字节,int类型变量赋值为1,这时候将其强转为char类型,读取的值还是1,说明就是小端模式。使用C语言就有两种方法可以区分机器的大小端。

第一种是使用联合体:

union test{ int a; char b;};
int main(void){ union test tmp; tmp.a = 1; if( tmp.b == 1){ printf("小端"); } else{ printf("大端"); }
getchar(); return 0;}

第二种是使用字符指针:

int main(void){ int a = 1; if( *(char*)&a == 1){ printf("小端"); } else{ printf("大端"); }
getchar(); return 0;}







还有没有其他方法可以表示unsigned char 的低3位和高5位?

解答
C语言位段的应用实例

使用union的好处在于,在我们对共用体中的结构体位段成员进行赋值时,我们可以通过unsigned char 的para成员直接进行获取,示例代码:
union para_t{ unsigned char para; struct { unsigned char codeformat:3; unsigned char backgroundmusic:5; }commandparameter_t;};int main(void){ union para_t test; test.commandparameter_t.backgroundmusic = 0x0a; test.commandparameter_t.codeformat = 0x01; printf("%x\n", test.para); getchar(); return 0;}








结语
《c和指针》一书中提及:用signed或unsigned整数显式地声明位段是个好主意,如果把位段声明为int类型,它究竟被解释为有符号数还是无符号数是由编译器所决定的。注重可移植性的程序应该避免使用位段。


END