初次接触位域

20 views
Skip to first unread message

Nicky H

unread,
Dec 27, 2011, 8:31:22 AM12/27/11
to Cortex-M3内核的应用
位域
位域是C语言中常用的位操作类型,位域可以节省字节空间,位域封装了C语言中位操作,编程人员可以很方便的利用位域在C语言上进行位操作,但
是,有利就有一弊,因为位域把C语言中的位操作都封装好了,所以编程人员很容易忘记位操作的本质,而且,使用位域还要注意一下几点:
1,字节顺序。字节顺序是指内存中多于一个字节类型的数据在内存中存放顺序,有小端,大端两种字节存放顺序。小端字节序(有的书上说是低端字节序)是指
低字节数据存放到内存低地址处,高字节数据存放到内存高地址处,大端字节序(有的地方叫高端字节序)则正好相反。不同的CPU有不通的字节顺序,实际编
程是要具体测试
2,当使用位域来进行封包时,有时候好几个变量使用同一个字节,这样,要注意几个变量地址的分配;例如:在单片机上读写SD时,要把SD的命令进行封包
发送,SD卡数据包如下图所示:

由此可以看出,数据包一共有6个字节,start_bit,transmission,commond共用一个字节,
这个时候初学者可能会这样定义位域:
struct _CMD_
{
unsigned char start_bit : 1;
unsigned char transmission : 1;
unsigned char commond :6;
unsigned char argument[4];
unsigned char crc_7 : 7;
unsigned char end_bit : 1;
};
大体一看。没错啊,就是这样啊!!可惜,这样是不对的,我在DEV-C++编译器上测试过,这样定义的话到最会有的苦头吃;在DEV-C++上,编译器
是这样把那一个字节给分配出来的:先分配低位地址,在struct _CMD_中,start_bit是第一位,所以,编译器先把那一个字节的最低位给
start_bit,把次低位分配给transmission,剩下的高六位给commond。我们再来看看上面那个图,start_bit是最高位,
所以,这样定义就会使得高低位混了,我们应该按照下面的方式定义:
typedef struct _CMD_
{
unsigned char commond : 6;
unsigned char transmission : 1;
unsigned char start_bit : 1;
unsigned char argument[4] ;
unsigned char end_bit : 1;
unsigned char crc_7 : 7;
}SD_CMD;
这样定义完后,start_bit就会成为最高位了。前提是发送数据包时先发送低位地址

以上是我以前的分析,现在又有了新的理解:
结构体和位域都是先分配低位地址的,也就是说,先定义的数据被分配到低位地址上,后定义的分配到高位地址上,以上的例子可以写为:
typedef struct _CMD_
{
unsigned char end_bit : 1;
unsigned char crc_7 : 7;
unsigned char argument[4] ;
unsigned char commond : 6;
unsigned char transmission : 1;
unsigned char start_bit : 1;
}SD_CMD;
这样,发送数据包的时候只要先发送高位地址就可以了
还有一点,封包发送需要用到指针的强制转换

杨萌

unread,
Dec 27, 2011, 7:49:35 PM12/27/11
to Cortex-M3内核的应用
学习了,看完以后感觉好晕,以后要注意这个问题啊,记得学习51的时候就分不清高低位的,
看来,在这儿也是一道坎啊,学习学习
mark
Reply all
Reply to author
Forward
0 new messages