[Tutor] I don't quite understand bitwise
Cameron Simpson
cs at cskk.id.au
Tue Dec 15 16:59:17 EST 2020
On 15Dec2020 19:11, nathan tech <nathan-tech at hotmail.com> wrote:
>So I'm working on a project that, as part of this project has a
>function called self.RegisterHotKey9arg1, arg2, arg3)
>
>It's wx python for context, but I don't think that is relevant.
>
>An example of this is:
>self.RegisterHotKey(self.kid6, win32con.MOD_ALT|win32con.MOD_SHIFT, 0x46)
>
>What I wanted to do was make it so that the second argument could be
>anything. I was sort of treating arg2 as a list, and so I'd do
>something like:
>
>l=["shift","windows","alt"]
>
>bit=None
>for x in l:
> bit=bit+x+|
>
>So I started to research how the x|y format works and came across
>bitwise operators which is apparrently what is meant when x|y|z is
>used.
Yes.
>But to me they look like ints/
They are ints.
So, we normally write integers in base 10, since we're raised learning
arithmetic that way and the Arabic number system uses 10 digits. So the
int 13 is the sum of 1*10 +3.
But we store integers in computers in base 2 because the basic storage
unit (a "bit") can hold one of 2 values. So in base 2 the value 13 it
composed of 1*8 + 1*4 + 0*2 + 1*1, and is written 1101 (or 0b1101 if
you're putting that in a Python programme).
So, bitmasks.
Instead if treating a bitmask as something we do arithmetic with, we
treat a bitmask as a sequence of independent bits, each indicating an
on/off or true/false status. We aren't _using_ them as "int"s/numbers,
we're using them as an array of 1/0 values.
They're just _stored_ in an int.
So your RegisterHotKey call has arg2 as
win32con.MOD_ALT|win32con.MOD_SHIFT is composing such an array. I don't
know the values of win32con.MOD_ALT etc, but each will normally be some
power of 2. Supposing we had these powers of 2 named:
win32con.MOD_ALT = 0b1000 # an 8
win32con.MOD_CTRL = 0b0100 # a 4
win32con.MOD_FN = 0b0010 # a 2
win32con.MOD_SHIFT = 0b0001 # a 1
The expression win32con.MOD_ALT|win32con.MOD_SHIFT is 0b1000|0b0001.
Which is 0b1001 - you're just setting particular bits within the value.
Doing another |win32con.MOD_SHIFT just sets 0b0001 again, which changes
nothing - it is already a 1.
The "|" is pronounced "or" (well, "bitwise or"). And "&" is pronounced
"and" (well, "bitwise and"). The result of a|b is a 1 if a=1 or b=1. The
result of a&b is 1 if a=1 and b=1. Each bit is treated independently.
So pretending the values above, win32con.MOD_ALT|win32con.MOD_SHIFT is
0b1001, which happens to b a 9 if you treat it as a number.
Doing things this way is effectively a compact way of passing around
combinations of true/false states, something you _might_ do verbosely in
Python like this:
RegisterHotKey(self.kid6, mod_alt=True, mod_shift=True, ...)
but it isn't written that way. The underlying reaons are twofold:
- who wants to write "mod_alt=True, mod_shift=True, ..." for this stuff?
- the underlying library will likely be a C or C++ library, and it is
routine to collect "flags" (true/false values) together in a bitmask
and just pass it around as an int.
Happy to elaborate further if anything is unclear.
Cheers,
Cameron Simpson <cs at cskk.id.au>
More information about the Tutor
mailing list