很久没有用C 语言中的 union 和 struct 位域操作了。

最近用了一下(当然,我承认是从stackoverflow 上抄的)

 

需求是这样的,已知一个 LPARAM 整数 3866625 ,求他的第30位的值是多少。

解法也挺简单

int a = 3866625;
a = a>>30 & 0x0001; //注意是右移动30,而不是29,因为第一位是0 ,我一开始就移动的29 结果算错!

但是我偶然在stack over flow 上看到了 另外一种方案

union KeyState
{
    LPARAM lparam;

    struct
    {
        unsigned nRepeatCount : 16;
        unsigned nScanCode : 8;
        unsigned nExtended : 1;
        unsigned nReserved : 4;
        unsigned nContext : 1;
        unsigned nPrev : 1;
        unsigned nTrans : 1;
    };
};

KeyState ks;
ks.lparam = 3866625;
ks.nPrev;  //这就是第30位


然后查了一下union,union的特点是,共享内存,且首地址相同。长度以最大的成员长度计算。

接着是struct 的位域操作符。

struct

{

unsigned a: 1;

unsigned b:2;

}

 

表示 a 成员占1个字节,b成员占2个字节。

 

把2者结合起来的效果是

 

当访问 union 的 nPrev  字段时,其实 是访问的是 :16+8+1+4+1 个位之后的位。且长度为1的值。比较起 位运算,虽然长了一点,但是非常容易理解了

 

更棒的是,可以任意访问其他的位了了。

 

这个位运算主要用计算 键盘扫描消息用。

 

Keystroke Message Flags

The lParam parameter of a keystroke message contains additional information about the keystroke that generated the message. This information includes the repeat count, the scan code, the extended-key flag, the context code, the previous key-state flag, and the transition-state flag. The following illustration shows the locations of these flags and values in the lParam parameter.

An application can use the following values to manipulate the keystroke flags.

KF_ALTDOWN Manipulates the ALT key flag, which indicated if the ALT key is pressed.
KF_DLGMODE Manipulates the dialog mode flag, which indicates whether a dialog box is active.
KF_EXTENDED Manipulates the extended key flag.
KF_MENUMODE Manipulates the menu mode flag, which indicates whether a menu is active.
KF_REPEAT Manipulates the repeat count.
KF_UP Manipulates the transition state flag.
posted on 2015-12-04 01:00  zooz  阅读(2506)  评论(0编辑  收藏  举报