您的位置:首页 > 其它

AD补码数据和位段结构体

2012-05-08 13:52 831 查看
转载自:

http://blog.sina.com.cn/s/blog_4513dde60100o6qn.html

这是调电路时遇到的问题。由12位AD传来的数据放入字长为32b的存储器里。其中存储器的数据线中低12b与AD相连,其余接地。AD数据使用12位补码表示。于是字长为32b的存储器里每个字存放的数据是由低12b的AD数据和高20b的0组成。如果再利用运行于CPU上的C程序对这些存储器中的数据进行处理,则无法直接使用。

例如,AD传送了数据-2,用12b的补码表示就是0xffe,但是在C程序中如果直接用32b的int类型来操作,就成了0xffe == 4094,两者相去甚远。只有进行一些附加的操作,比如,判断数据的11b(最低位为0b)是否等于1,若是,则将数据的高20b置1,写成代码就是:

if ((x & 0x800) != 0) x |= 0xfffff000;

我想,在C的层面上是否有更简便而灵活的操作方法。假如说我们的AD换成了4b,6b,8b,14b,16b,18b,20b等等(好像AD没有这么多类),那么上面代码中的0x800和0xfffff000就要换成相应的数值才行,虽然不很麻烦,但也有点麻烦。

那天看以前写的程序,发现位段结构体中位域都使用unsigned修饰的。我想,位域大概也可以用signed修饰吧!好像从来没有这样做过。如果能行,我们是不是找到了一种应对AD有符号补码数据的灵活方法呢?于是写了一段代码验证想法,如下:

// bitstruct.cpp : 定义控制台应用程序的入口点。

//



#include "stdafx.h"

#include<stdlib.h>

typedef unsigned int UINT;

#define INTBITS(WIDTH) \

typedef struct \

{ \

signed ad : WIDTH; \

unsigned unused : 32 - WIDTH; \

} INT##WIDTH

int _tmain(int argc, _TCHAR* argv[])

{

UINT x;

INTBITS(12); // Now struct INT12 is available

INTBITS(14);
// Now struct INT14 is available

x = 0x00000ffe;

printf(

"x == 0x%x\n"

"12 bits signed number of x == %d\n",

x,

(reinterpret_cast<INT12*>(&x))->ad

);

x = 0x00003ffe;

printf(

"x == 0x%x\n"

"14 bits signed number of x == %d\n",

x,

(reinterpret_cast<INT14*>(&x))->ad

);

system("pause");

return 0;

}





程序的结果表明,这种方法的确运行正确。

程序的关键在于宏INTBITS,它有一个参数WIDTH,用来表示AD的位数,可以代入12,14这样的整数,不过千万不要代入12+2这样的表达式。代入不同的整数,INTBITS会定义不同的结构体,INTBITS(12)会定义名为INT12的结构体,它的位域ad代表12b的有符号补码形式整数,INTBITS(14)会定义名为INT14的结构体,它的位域ad代表14b有符号补码形式整数,其余依次类推,只要AD数据不超过32b,直接使用ad域就行。

2009年10月26日补充:在《AD补码数据和位段结构体(续)》中,使用template而不是Macro来实现代码中的位段结构体。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: