33
Bitwise Operations

In the first part of this book, I described the memory of a computer as a vast meadow of switches (billions of switches) that could be turned on or off. Each switch represents one bit, and we usually use 1 to mean on and 0 to mean off.

However, you never address a single bit. Instead, you deal with byte-sized chunks of bits. If you think of a byte as an unsigned 8-bit integer, each bit represents another power of two:

Figure 33.1  One byte representing the decimal number 60

One byte representing the decimal number 60

As a side-effect of living with 10 fingers, people like to work with decimal numbers (base-10). Computers, however, like powers of 2. Programmers often use a base-16 number system (16 = 24) known as hexadecimal or just hex. This is especially true when we are dealing with individual bits of an integer.

We use the letters a, b, c, d, e, and f for the extra digits. Thus, counting in hex goes like this: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, 10, 11,

To make it clear when we are writing in hex, we prefix the number with 0x. Here is the same number and byte expressed using hex:

Figure 33.2  One byte representing the hex number 0x3c

One byte representing the hex number 0x3c

Note that one byte can always be described as a two-digit hex number (like 3c). This makes hex a reasonable way to look at binary data. A tough-guy programmer thing to say is I reversed engineered the file format by studying the document files in a hex editor. Want to see a file as a list of hex-encoded bytes? In Terminal, run hexdump on the file:

$​ ​h​e​x​d​u​m​p​ ​m​y​f​i​l​e​.​t​x​t​
0​0​0​0​0​0​0​ ​3​c​ ​3​f​ ​7​8​ ​6​d​ ​6​c​ ​2​0​ ​7​6​ ​6​5​ ​7​2​ ​7​3​ ​6​9​ ​6​f​ ​6​e​ ​3​d​ ​2​2​ ​3​1​
0​0​0​0​0​1​0​ ​2​e​ ​3​0​ ​2​2​ ​3​f​ ​3​e​ ​0​a​ ​3​c​ ​6​2​ ​6​f​ ​6​f​ ​6​b​ ​2​0​ ​7​8​ ​6​d​ ​6​c​ ​6​e​
0​0​0​0​0​2​0​ ​7​3​ ​3​d​ ​2​2​ ​6​8​ ​7​4​ ​7​4​ ​7​0​ ​3​a​ ​2​f​ ​2​f​ ​6​4​ ​6​f​ ​6​3​ ​6​2​ ​6​f​ ​6​f​
0​0​0​0​0​3​0​ ​6​b​ ​2​e​ ​6​f​ ​7​2​ ​6​7​ ​2​f​ ​6​e​ ​7​3​ ​2​f​ ​6​4​ ​6​f​ ​6​3​ ​6​2​ ​6​f​ ​6​f​ ​6​b​
0​0​0​0​0​4​0​ ​2​2​
0​0​0​0​0​4​1​ ​

The first column is the offset (in hex) from the beginning of the file of the byte listed in the second column. Each two digit number represents one byte.

Bitwise-OR

If you have two bytes, you can bitwise-OR them together to create a third byte. A bit on the third byte will be 1 if at least one of the corresponding bits in the first two bytes is 1.

Figure 33.3  Two bytes bitwise-ORed together

Two bytes bitwise-ORed together

This is done with the | operator. To try your hand at manipulating bits, create a new project: a C Command Line Tool (not Foundation) named bitwize.

Edit main.c:

#​i​n​c​l​u​d​e​ ​<​s​t​d​i​o​.​h​>​

i​n​t​ ​m​a​i​n​ ​(​i​n​t​ ​a​r​g​c​,​ ​c​o​n​s​t​ ​c​h​a​r​ ​*​ ​a​r​g​v​[​]​)​
{​
 ​ ​ ​ ​u​n​s​i​g​n​e​d​ ​c​h​a​r​ ​a​ ​=​ ​0​x​3​c​;​
 ​ ​ ​ ​u​n​s​i​g​n​e​d​ ​c​h​a​r​ ​b​ ​=​ ​0​x​a​9​;​
 ​ ​ ​ ​u​n​s​i​g​n​e​d​ ​c​h​a​r​ ​c​ ​=​ ​a​ ​|​ ​b​;​

 ​ ​ ​ ​p​r​i​n​t​f​(​"​H​e​x​:​ ​%​x​ ​|​ ​%​x​ ​=​ ​%​x​​n​"​,​ ​a​,​ ​b​,​ ​c​)​;​
 ​ ​ ​ ​p​r​i​n​t​f​(​"​D​e​c​i​m​a​l​:​ ​%​d​ ​|​ ​%​d​ ​=​ ​%​d​​n​"​,​ ​a​,​ ​b​,​ ​c​)​;​

 ​ ​ ​ ​r​e​t​u​r​n​ ​0​;​
}​

When you run this program, you will see the two bytes bitwise-ORed together:

H​e​x​:​ ​3​c​ ​|​ ​a​9​ ​=​ ​b​d​
D​e​c​i​m​a​l​:​ ​6​0​ ​|​ ​1​6​9​ ​=​ ​1​8​9​

What’s this good for? In Objective-C, we often use an integer to specify a certain setting. An integer is always a sequence of bits, and each bit is used to represent one aspect of the setting that can be turned on or off. We create this integer (also known as a bit mask) by picking and choosing from a set of constants. These constants are integers, too, and each constant specifies a single aspect of the setting by having only one of its bits turned on. You can bitwise-OR together the constants that represent the particular aspects you want. The result is the exact setting you’re looking for.

Let’s look at an example. iOS comes with a class called NSDataDetector. Instances of NSDataDetector go through text and look for common patterns like dates or URLs. The patterns an instance will look for is determined by the bitwise-OR result of a set of integer constants.

NSDataDetector.h defines these constants: NSTextCheckingTypeDate, NSTextCheckingTypeAddress, NSTextCheckingTypeLink, NSTextCheckingTypePhoneNumber, and NSTextCheckingTypeTransitInformation. When you create an instance of NSDataDetector, you tell it what to search for. For example, if you wanted it to search for phone numbers and dates, you would do this:

N​S​E​r​r​o​r​ ​*​e​;​
N​S​D​a​t​a​D​e​t​e​c​t​o​r​ ​*​d​ ​=​ ​[​N​S​D​a​t​a​D​e​t​e​c​t​o​r​ ​d​a​t​a​D​e​t​e​c​t​o​r​W​i​t​h​T​y​p​e​s​:​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​N​S​T​e​x​t​C​h​e​c​k​i​n​g​T​y​p​e​P​h​o​n​e​N​u​m​b​e​r​|​N​S​T​e​x​t​C​h​e​c​k​i​n​g​T​y​p​e​D​a​t​e​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​e​r​r​o​r​:​&​e​]​;​

Notice the bitwise-OR operator. You’ll see this pattern a lot in Cocoa and iOS programming, and now you’ll know what’s going on behind the scenes.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset