有一天,我试图代码中使用SDL多媒体库中的小C ++编程,我就遇到了这个小障碍,我最终通过试验和错误解决。 问题是,我明白我做了什么来解决这个问题,但我真的不明白这个问题的本质!
问题是与键盘事件处理SDL。 处理单个按键退出程序的代码是直线前进和简单。 [EventQueue的是SDL_Event结构]
//checks for keypress events..
if ( eventQueue.type == SDL_KEYDOWN )
{
//note: uses the boolean logical '==' equals operator..
if ( eventQueue.key.keysym.sym == SDLK_ESCAPE )
{
running = false;
}
}
在上面的代码,只需按下自身ESCAPE键结束主回路和导致程序清理和关闭...
但是...处理使用修饰键按键所需要的代码(移动/ ALT / CTRL)没有用“==”操作的工作是正确的。 我花了好长时间才发现,我需要使用,而不是平等的(逻辑?)运算符按位与运算符。
//checks for keypress events..
if ( eventQueue.type == SDL_KEYDOWN )
{
//note: requires the use of the bitwise AND operator..
if (( eventQueue.key.keysym.mod & KMOD_ALT ) && (eventQueue.key.keysym.sym == SDLK_F4 ))
{
running = false;
}
}
在这里,我的困惑来自于,使用“keysym.sym”成员时,逻辑运算符“==”工作正常,但是,使用“keysym.mod”成员时,使用“&”是必要的事实按位与运算。
现在,如果我猜的话,我会说,这事做的事实,“keysym.sym”只处理一个单一的数值表示键盘上的一个键,而“keysym.mod”有对付Shift,Ctrl的各种组合,和Alt键...?
综上所述,我的问题:为什么会出现这种情况? 反正是有学习,比试验和错误等,有一定的数据块是否需要按位或逻辑/相等运算符进行比较? 为什么说“keysym.sym == SDLK_F4”工作正常,但“keysym.mod == KMOD_ALT”不? 为什么会涉及十进制数的操作有一个不同的结果比比较位值的操作? 是否有也是在逻辑运算工作,位运算是行不通的情况呢?
该位与有点特殊。 ==
平等,但位AND运算符的检查可以让你用一个数的各个位工作。
想象一下,你的事件定义为键的列表:
event = ['a', 'shift', 'ctrl']
然后,您可以检查,看是否有特定的改性剂是事件的一部分,很容易地:
if 'shift' in event:
# ...
按位AND是有点像一个in
声明。 您可以定义事件作为这样一个二进制数:
event = 00010010
现在,当你执行的位与,你可以很容易地检查,看是否有一定的修改已经被应用到该事件作为修饰也表示为二进制数:
00010001 # event (18)
& 00010000 # shift key (8)
----------
00010000 # you get a non-zero answer, so the shift key is in the event
----------
00010001 # event (18)
& 00001000 # "z" key (4)
----------
00000000 # you get zero because the "z" key wasn't a part of the event
----------
您可以使用按位或构建这样一个事件:
00000001 # shift key (1)
| 10100000 # "a" key (160)
----------
10100001 # resulting event (161)
----------
维基百科总结了位操作相当不错:
按位操作的一个或多个位模式或二进制数在它们的各个位的级别运行。 它是由处理器直接支持一个快速,原始的动作,并用于操纵用于比较和计算值。 上简单的低成本的处理器,通常,按位操作比划分明显更快,比乘法快几倍,而且比另外有时显著更快。 虽然现代的处理器通常是由于其较长的指令流水线等建筑设计选择执行加法和乘法一样快位运算,位运算做通常使用的,因为减少了资源的使用更少的功耗/性能。
基本上,按位运算符允许你存储在一个整数的有效比特的信息工作。
你在这里做
eventQueue.key.keysym.mod & KMOD_ALT
是不是比较操作,这是一个位掩码操作。 比较操作是在C和C ++隐式:该计算结果为零的表达的意思是“假”时,所有的非零值表示“真”。 当在你们这样一个逻辑表达式中使用,这是一个速记
(eventQueue.key.keysym.mod & KMOD_ALT) != 0
现在到了位操作:一定值代表两个或多个值的位组合。 例如, keysym.sym
表示用于ALT的位模式的组合(其本身是左和右ALT的组合)和任何其它键,其可以在同一时间被压。 从组合中分离一个值,位屏蔽技术被用于:具有在所有其他位利息和零位的人(这是一个值KMOD_ALT
)是AND-ED与组合值(在你的情况,它的keysym.sym
)产生的比特keysym.sym
中所指示的比特1
S的KMOD_ALT
。
最终的结果是, eventQueue.key.keysym.mod & KMOD_ALT
将只有当ALT被按下不为零。
免责声明:我知道旁边没有关于SDL。 什么我在这里回答大多是猜测。
有一个数字,预计无论其他按键多少压产生的关键事件键盘上的按键。 修改键如Shift,Alt键 ,Ctrl键是这样钥匙(不知道是否有更多的)和键盘制造商必须确保它们可以同时被按下。 按键的其余部分是正常的键,如果同时按下,这取决于每一个键盘的电路上可能会,也可能不会产生一个关键事件。
当按下键正常,关键事件触发(不知道是否按下组合键将触发一个事件)。 正常的关键是在sym
以及是否有任何修改键被按下,在正常按键被记录在时间mod
。 我敢肯定,在实施的角度来看,某一位mod
用来定义某些修改键是否被按下。 要检查位是否被开启或没有,你需要逐位&
与定义该位用于指示修改键是否被按下不恒定。
文章来源: Why do certain situations require the use of 'bitwise' operators instead of 'logical' / 'equality' operators?