51

I have been reading about bit operators in Objective-C in Kochan's book, "Programming in Objective-C".

I am VERY confused about this part, although I have really understood most everything else presented to me thus far.

Here is a quote from the book:

The Bitwise AND Operator

Bitwise ANDing is frequently used for masking operations. That is, this operator can be used easily to set specific bits of a data item to 0. For example, the statement

w3 = w1 & 3;

assigns to w3 the value of w1 bitwise ANDed with the constant 3. This has the same ffect of setting all the bits in w, other than the rightmost two bits to 0 and preserving the rightmost two bits from w1.

As with all binary arithmetic operators in C, the binary bit operators can also be used as assignment operators by adding an equal sign. The statement

word &= 15;

therefore performs the same function as the following:

word = word & 15;

Additionally, it has the effect of setting all but the rightmost four bits of word to 0. When using constants in performing bitwise operations, it is usually more convenient to express the constants in either octal or hexadecimal notation.

OK, so that is what I'm trying to understand. Now, I'm extremely confused with pretty much this entire concept and I am just looking for a little clarification if anyone is willing to help me out on that.

When the book references "setting all the bits" now, all of the bits.. What exactly is a bit. Isn't that just a 0 or 1 in 2nd base, in other words, binary?

If so, why, in the first example, are all of the bits except the "rightmost 2" to 0? Is it 2 because it's 3 - 1, taking 3 from our constant?

Thanks!

Qcom
  • 18,263
  • 29
  • 87
  • 113
  • Related: [Bitwise operation and usage](https://stackoverflow.com/q/1746613) for bitwise boolean ops in general, pointing out that they do 32 (or 64 or whatever) separate bitwise boolean operations in parallel. – Peter Cordes Feb 23 '22 at 08:49

4 Answers4

154

Numbers can be expressed in binary like this:

3    = 000011
5    = 000101
10   = 001010

...etc. I'm going to assume you're familiar with binary.

Bitwise AND means to take two numbers, line them up on top of each other, and create a new number that has a 1 where both numbers have a 1 (everything else is 0).

For example:

    3          =>  00011
  & 5          =>  00101
------           -------
    1              00001

Bitwise OR means to take two numbers, line them up on top of each other, and create a new number that has a 1 where either number has a 1 (everything else is 0).

For example:

    3          =>  00011
  | 5          =>  00101
------           -------
    7              00111

Bitwise XOR (exclusive OR) means to take two numbers, line them up on top of each other, and create a new number that has a 1 where either number has a 1 AND the other number has a 0 (everything else is 0).

For example:

    3          =>  00011
  ^ 5          =>  00101
------           -------
    6              00110  

Bitwise NOR (Not OR) means to take the Bitwise OR of two numbers, and then reverse everything (where there was a 0, there's now a 1, where there was a 1, there's now a 0).

Bitwise NAND (Not AND) means to take the Bitwise AND of two numbers, and then reverse everything (where there was a 0, there's now a 1, where there was a 1, there's now a 0).

Continuing: why does word &= 15 set all but the 4 rightmost bits to 0? You should be able to figure it out now...

     n          =>  abcdefghjikl
  & 15          =>  000000001111
------            --------------
     ?              00000000jikl

(0 AND a = 0, 0 AND b = 0, ... j AND 1 = j, i AND 1 = i, ...)

How is this useful? In many languages, we use things called "bitmasks". A bitmask is essentially a number that represents a whole bunch of smaller numbers combined together. We can combine numbers together using OR, and pull them apart using AND. For example:

int MagicMap = 1;
int MagicWand = 2;
int MagicHat = 4;

If I only have the map and the hat, I can express that as myInventoryBitmask = (MagicMap | MagicHat) and the result is my bitmask. If I don't have anything, then my bitmask is 0. If I want to see if I have my wand, then I can do:

int hasWand = (myInventoryBitmask & MagicWand);
if (hasWand > 0) {
  printf("I have a wand\n");
} else {
  printf("I don't have a wand\n");
}

Get it?

EDIT: more stuff

You'll also come across the "bitshift" operator: << and >>. This just means "shift everything left n bits" or "shift everything right n bits".

In other words:

1 << 3 = 0001 << 3 = 0001000 = 8

And:

8 >> 2 = 01000 >> 2 = 010 = 2

Dave DeLong
  • 242,470
  • 58
  • 448
  • 498
  • 2
    WOW! Thank you very much for this response. According, to this calculator online: http://www.convertit.com/go/convertit/calculators/math/base_converter.asp 3 = 11 5 = 101 10 = 1010 Did you prefix your binary numbers or something like that? – Qcom Aug 06 '10 at 20:49
  • 2
    @BOSS yeah I prefix with 0 to make them line up and to make sure they're not negative "2s-complement" numbers. – Dave DeLong Aug 06 '10 at 20:50
  • @Dave OK, thanks I've heard about that somewhere before, and I'm guessing that every binary number begins with a 1? Anyway, Still a little confused about the example with word &= 15. Let me see if I got this: Basically, as you said, since j and 1 = j, this is because there is a 1, and a bit that isn't 0? Conversely, 0 AND a = 0 because there is no 1 paired with the a? – Qcom Aug 06 '10 at 20:54
  • @BOSS yep, you got it! It helps to think about it words: `YES AND NO = NO`, `YES OR NO = YES`, `YES NOR NO = NOT(YES OR NO) = NO`, etc. – Dave DeLong Aug 06 '10 at 20:57
  • @Dave I really really appreciate your help! That is AWESOME! :) I'm surprised my book didn't explain it a little better. I think the book is pretty good thus far, but I could have used a lot more background info. And yes! The words help even more xD. I'm a little more confused about the last example you showed me, of course that's the more useful one! But I'm kind of picking it apart, and it's becoming clearer. If I get what you mean, then they can pretty useful then, can't they? – Qcom Aug 06 '10 at 21:01
  • 1
    @BOSS they are very useful. It works because you essentially treat each "column" of the bitmask as an "on/off switch" that represents one item (in this example, your inventory). You define the items such that (in binary) they only have a single 1, with all the rest being 0. This means you can OR them together and not lose any information. It's REALLY useful, and you'll see them a LOT in Cocoa (most methods that have an `options:` parameter are asking for a bitmask of options) – Dave DeLong Aug 06 '10 at 21:05
  • @Dave, yeah, those shift operators also appeared in my book. Thanks so much! – Qcom Aug 06 '10 at 21:09
  • Just wondering, apparently these bitmasks can also be used for sprites (http://en.wikipedia.org/wiki/Mask_(computing)#Image_masks). Would it be possible, once I'm farther along in my objc-c understanding, to develop a side-scrolling game using this method? – Qcom Aug 06 '10 at 22:04
  • Yes, you can use a bitmask to perform 1-bit alpha blending. This technique is a bit of a relic from days past when memory and processing power were more limited. If you're going to be writing a game, you'll want to use libraries like OpenGL that take care of alpha blending for you. Less work, and you'll get 8-bit alpha transparency for free. – Ryan Ballantyne Aug 06 '10 at 23:28
  • OK, cool, now that I think about it, wasn't that pac-man on that wikipedia article?! :) Thanks though. – Qcom Aug 07 '10 at 00:31
  • why this answer uses 6 bits to represent an integer instead of 8 bits ? – Raghu Sep 13 '20 at 10:54
  • wonderful comment, now I have understood what does it mean bit AND OR XOR, very interesting, thanks !! – CuteMeowMeow Nov 08 '22 at 02:27
2

"Bit" is short for "binary digit". And yes, it's a 0 or 1. There are almost always 8 in a byte, and they're written kinda like decimal numbers are -- with the most significant digit on the left, and the least significant on the right.

In your example, w1 & 3 masks everything but the two least significant (rightmost) digits because 3, in binary, is 00000011. (2 + 1) The AND operation returns 0 if either bit being ANDed is 0, so everything but the last two bits are automatically 0.

cHao
  • 84,970
  • 20
  • 145
  • 172
1
w1 =    ????...??ab
3  =    0000...0011
--------------------
&  =    0000...00ab

0 & any bit N = 0

1 & any bit N = N

So, anything bitwise anded with 3 has all their bits except the last two set to 0. The last two bits, a and b in this case, are preserved.

insipid
  • 3,238
  • 3
  • 26
  • 38
1

@cHao & all: No! Bits are not numbers. They’re not zero or one!

Well, 0 and 1 are possible and valid interpretations. Zero and one is the typical interpretation.

But a bit is only a thing, representing a simple alternative. It says “it is” or “it is not”. It doesn’t say anything about the thing, the „it“, itself. It doesn’t tell, what thing it is.

In most cases this won’t bother you. You can take them for numbers (or parts, digits, of numbers) as you (or the combination of programming languages, cpu and other hardware, you know as being “typical”) usaly do – and maybe you’ll never have trouble with them.

But there is no principal problem if you switch the meaning of “0“ and “1”. Ok, if doing this while programming assembler, you’ll find it a bit problematic as some mnemonics will do other logic then they tell you with their names, numbers will be negated and such things.

Have a look at http://webdocs.cs.ualberta.ca/~amaral/courses/329/webslides/Topic2-DeMorganLaws/sld017.htm if you want.

Greetings

  • 1
    Love how this answer waffles. Bits are not zero or one!...except when they are represented by 0 and 1, which is the typical representation. But there is no problem if you switch the meaning of "0" and "1"...except if you're programming in assembler, then it's problematic. This view is somewhere between uselessly pedantic and insane. – cHao Jun 01 '15 at 17:46
  • Sounds like a victim of purism. – NYC Tech Engineer Nov 19 '15 at 18:39