AD补码数据和位段结构体

转载自:

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;
}


 

AD补码数据和位段结构体

     程序的结果表明,这种方法的确运行正确。
     程序的关键在于宏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来实现代码中的位段结构体。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值