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:
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:
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:
$ hexdump myfile.txt
0000000 3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e 3d 22 31
0000010 2e 30 22 3f 3e 0a 3c 62 6f 6f 6b 20 78 6d 6c 6e
0000020 73 3d 22 68 74 74 70 3a 2f 2f 64 6f 63 62 6f 6f
0000030 6b 2e 6f 72 67 2f 6e 73 2f 64 6f 63 62 6f 6f 6b
0000040 22
0000041
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.
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.
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:
#include <stdio.h> int main (int argc, const char * argv[]) { unsigned char a = 0x3c; unsigned char b = 0xa9; unsigned char c = a | b; printf("Hex: %x | %x = %xn", a, b, c); printf("Decimal: %d | %d = %dn", a, b, c); return 0; }
When you run this program, you will see the two bytes bitwise-ORed together:
Hex: 3c | a9 = bd Decimal: 60 | 169 = 189
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:
NSError *e; NSDataDetector *d = [NSDataDetector dataDetectorWithTypes: NSTextCheckingTypePhoneNumber|NSTextCheckingTypeDate error:&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.