Why do certain situations require the use of 'bitwise' operators instead of 'logical' / 'equality' operators?

喜夏-厌秋 提交于 2019-12-23 20:58:59

问题


The other day I was trying to code a small C++ programming using the SDL multimedia library, and I ran into this small snag which I eventually solved through trial and error. The issue is, I understand what I did to solve the problem, but I don't really understand the nature of the problem!

The issue was with keyboard event handling in SDL. The code to handle a single key press to exit the program is straight forward and simple. [eventQueue is an SDL_Event structure]

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

In the above code, simply pressing the ESCAPE key on its own ends the main loop and causes the program to clean up and close...

However... The code needed to handle key presses that use modifier keys (shift/alt/ctrl) did not work correct with the '==' operator. It took me ages to find out that I needed to use a bitwise AND operator instead of the equality (logical?) operator.

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

My confusion here comes from the fact that, when using the 'keysym.sym' member, the logical operator '==' works fine, however, when using the 'keysym.mod' member, it was necessary to use the '&' bitwise AND operator.

Now, if I had to guess, I would say that it has something to do with the fact that 'keysym.sym' only has to handle a single numerical value that represents a single key on the keyboard, while 'keysym.mod' has to deal with various combinations of shift, ctrl, and alt keys...?

To sum up my question: Why is this the case? Is there anyway to learn, other than trial and error, whether a certain piece of data will need to be compared with bitwise or logical/equality operators? Why is it that "keysym.sym == SDLK_F4" works fine, but "keysym.mod == KMOD_ALT" does not? Why would an operation involving decimal numbers have a different result than an operation that compares the bit values? Are there also situations where logical operations work and bitwise operations would not work?


回答1:


The bitwise AND is somewhat special. == checks for equality but the bitwise AND operator allows you to work with the individual bits of a number.

Imagine your event was defined as a list of keys:

event = ['a', 'shift', 'ctrl']

You can then check to see if a particular modifier is a part of the event pretty easily:

if 'shift' in event:
  # ...

The bitwise AND is sort of like an in statement. You can define your event as a binary number like this:

event = 00010010

Now, when you perform the bitwise AND, you can easily check to see if a certain modifier has been applied to the event, as modifiers are also represented as binary numbers:

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

You can construct an event like this using the bitwise OR:

  00000001  # shift key (1)
| 10100000  # "a" key (160)
----------
  10100001  # resulting event (161)
----------

Wikipedia sums up bitwise operations pretty well:

A bitwise operation operates on one or more bit patterns or binary numerals at the level of their individual bits. It is a fast, primitive action directly supported by the processor, and is used to manipulate values for comparisons and calculations. On simple low-cost processors, typically, bitwise operations are substantially faster than division, several times faster than multiplication, and sometimes significantly faster than addition. While modern processors usually perform addition and multiplication just as fast as bitwise operations due to their longer instruction pipelines and other architectural design choices, bitwise operations do commonly use less power/performance because of the reduced use of resources.

Basically, bitwise operators allow you to work with information stored in the bits of an integer efficiently.




回答2:


What you did here

eventQueue.key.keysym.mod & KMOD_ALT

is not a compare operation, it is a bit masking operation. The compare operation is implicit in C and C++: an expression that evaluates to zero means "false", all non-zero values mean "true". When used in a logic expression like yours, this is a shorthand for

(eventQueue.key.keysym.mod & KMOD_ALT) != 0

Now to the bit operations: certain values represent bit combinations of two or more values. For example, keysym.sym represents a combination of a bit pattern for ALT (which is itself a combination of the left and the right ALT) and whatever other key that may be pressed at the same time. To separate one value from a combination, a bit masking technique is used: a value that has ones in the bits of interest and zeros in all other bits (that's KMOD_ALT) is AND-ed with the combination value (in your case, it's keysym.sym) producing the bits of keysym.sym in the bits indicated by 1s of KMOD_ALT.

The net result is that eventQueue.key.keysym.mod & KMOD_ALT will be non-zero only if the ALT has been pressed.




回答3:


Disclaimer: I know next to nothing about SDL. What I'm answering here is mostly from guesswork.

There are a number of keys on the keyboard that are expected to generate a key event no matter how many other keys are pressed. The modifier keys such as Shift, Alt, Ctrl are such keys (not sure if there are more) and the keyboard manufacturer must make sure they can be pressed simultaneously. The rest of the keys are normal keys, and might or might not generate a key event if pressed simultaneously, depending on the circuit of each keyboard.

When normal key is pressed, a key event is trigger (not sure whether pressing modifier keys would trigger an event). The normal key is in sym and whether any modifier key is being pressed at the time the normal key is pressed is recorded in mod. I'm quite sure, implementation-wise, certain bit in the mod is used to define whether certain modifier key is pressed or not. To check whether the bit is turned on or not, you need to bit wise & with the constant that defines which bit is used to indicate whether the modifier key is pressed or not.



来源:https://stackoverflow.com/questions/11945481/why-do-certain-situations-require-the-use-of-bitwise-operators-instead-of-log

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!