Bitwise Guide
Bitwise Explanation
Hopefully as you know, everything in computers in made of binary at its lowest level. Every 1 and 0 in binary is called a bit, and every 8 bits is called a byte. This structure forms everything on the computer representing character and numbers to more complex operations to advanced to cover here.
Bitwise Operations are functions designed to manipulate these bits. This can be used for various reason but commonly its used to manually flip the binary 1's and 0's in order for the programmer to store new information in the same amount of space. You can see these functions here in the bit library.
Explanation
Now that you have some fundamental understanding of what bitwise operations lets walk through and example to reinforce your understanding.
The following is a code snippet that "packs" a RGBA value into a 32 bit long int value (represented by Hexadecimal form).
Now lets break this down operation by operation so you can understand how we use bitwise operations to manually flip these bits.
Packing Process
before we begin lets first visualize the length of binary that we wanna return. because we are wanting to return a number, we will want to return 32 bits:
Each space represent the 8 bits that make up 1 byte.
For this example our r
value will be 255 (in binary its 11111111
) lets add this to our int from step 1:
now in order to add more bits to this int we will first need to move our value of 255 out of the way, we do this using the bit.lshift function which will take the value we wanna use (255 or 11111111
) and move it to the left but n
amount of bits.
since we are wanting to move our value to the beginning byte we will need to move it left by 24 bits
we will do this operation for every subsequent RGBA component:
Now because we only have the last 8 bits (or byte) left we can just add our a
value to the end with our final bitwise operation.
- The
bit.bor
operation only exists here to encompass everything as a bitwise number, it servers no logical benefit TO THIS SNIPPET SPECIFCALLY.
And that's it for the packing process, what we just completed was the process of taking 4 numerical values and representing them using 1 larger value. Now for the
The Why
Its mainly to save on storage, this can easily be seen if we just compare the actual bits of information the computer sees:
Unpacking Process
Now that you know what we are doing the unpacking process is a lot easier. we just simply need to extract our information back out.
All we have to do to is isolate the values out that we wanna extract, we can do this by using the hexadecimal values
Bit flags
Bit flags (or bitflags) are flags that are stored within a single number, where each bit on a 32bit integer (or larger) is a separate flag.
By their nature they can be combined together, via using the Bitwise OR operation, such as with bit.bor.
For example, take the FL enum. We can combine FL_NPC
(value of 16384) and FL_GODMODE
(value of 32768) together like so
Bit flags can be tested via Bitwise AND operation. If we take the above operation, and store its result in a variable, we can then test it whether a specific flag (or multiple) are set within a number like so:
Finally, bitflags can be removed via the bitwise BAND and NOT operations, like so:
Bitwise operations cannot be used on enumerations that are sequential, i.e. 1,2,3,4,5,6, etc., such as HUD enum.