38
Bitwise Operations

In the first part of this book, we 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 38.1  One byte representing the decimal number 60

One byte representing the decimal number 60

As a side-effect of evolving to have 10 fingers, people like to work with decimal numbers (base-10). Computers, as a side-effect of evolving to use switches that could only be on or off, 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 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 38.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 reverse-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 38.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 is 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 are 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 are 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. Each of the numbers being ORed together has exactly one bit on, so the resulting bit mask would have two bits on. You will see this pattern a lot in Cocoa and iOS programming, and now you will know what is 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