为什么某些情况需要使用"按位"运算符而不是"逻辑"/"相等"运算符?

MrK*_*ish 3 c++ boolean-logic sdl event-handling bitwise-operators

有一天,我试图使用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,只需按下ESCAPE键就可以结束主循环并导致程序清理和关闭......

但是...处理使用修饰键(shift/alt/ctrl)的按键所需的代码与'=='运算符无法正常工作.我花了很长时间才发现我需要使用按位AND运算符而不是相等(逻辑?)运算符.

//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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的困惑来自这样一个事实:当使用'keysym.sym'成员时,逻辑运算符'=='工作正常,但是,当使用'keysym.mod'成员时,有必要使用'&'按位AND运算符.

现在,如果我不得不猜测,我会说它与'keysym.sym'只需要处理一个代表键盘上单个键的数字值这一事实有关,而'keysym.mod'有处理shift,ctrl和alt键的各种组合......?

总结一下我的问题:为什么会这样?除了试验和错误之外,还有什么需要学习某个数据是否需要与按位或逻辑/相等运算符进行比较?为什么"keysym.sym == SDLK_F4"工作正常,但"keysym.mod == KMOD_ALT"没有?为什么涉及十进制数的操作与比较位值的操作有不同的结果?是否还存在逻辑运算工作和按位运算不起作用的情况?

Ble*_*der 5

按位AND有点特殊.==检查是否相等,但按位AND运算符允许您使用数字的各个位.

想象一下,您的事件被定义为键列表:

event = ['a', 'shift', 'ctrl']
Run Code Online (Sandbox Code Playgroud)

然后,您可以非常轻松地检查特定修改器是否是事件的一部分:

if 'shift' in event:
  # ...
Run Code Online (Sandbox Code Playgroud)

按位AND有点像in声明.您可以将事件定义为二进制数,如下所示:

event = 00010010
Run Code Online (Sandbox Code Playgroud)

现在,当您执行按位AND时,您可以轻松检查是否已将某个修改器应用于事件,因为修饰符也表示为二进制数:

  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
----------
Run Code Online (Sandbox Code Playgroud)

您可以使用按位OR构造这样的事件:

  00000001  # shift key (1)
| 10100000  # "a" key (160)
----------
  10100001  # resulting event (161)
----------
Run Code Online (Sandbox Code Playgroud)

维基百科很好地总结了按位运算:

按位操作在其各个位的级别上对一个或多个位模式或二进制数字进行操作.它是处理器直接支持的快速原始操作,用于操作值以进行比较和计算.在简单的低成本处理器上,通常,按位运算比除法快得多,比乘法快几倍,有时比加法快得多.虽然现代处理器由于其较长的指令流水线和其他架构设计选择,通常执行加法和乘法,与按位运算一样快,但由于资源使用减少,按位运算通常使用较少的功率/性能.

基本上,按位运算符允许您有效地处理存储在整数位中的信息.