很久没有用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. |