Arithmetic operators are straightforward (K&R 2.5), but watch out for the rule that “integer division truncates any fractional part.” This rule is the cause of much novice error in C. If you have two integers and you want to divide them in such a way as to get a fractional result, you must represent at least one of them as a float:
int i = 3; float f = i/2; // beware! not 1.5
To get 1.5, you should have written i/2.0
or (float)i/2
.
The integer increment and decrement operators (K&R 2.8), ++
and --
, work differently depending on whether they precede or follow their variable. The expression ++i
replaces the value of i
by 1 more than its current value and then uses the resulting value; the expression i++
uses the current value of i
and then replaces it with 1 more than its current value. This is one of C’s coolest features.
C also provides bitwise operators (K&R 2.9), such as bitwise-and (&
) and bitwise-or (|
); they operate on the individual binary bits that constitute integers. Of these, the one you are most likely to need is bitwise-or, because the Cocoa API often uses bits as switches when multiple options are to be specified simultaneously. For example, there are various ways in which a UIView can be resized automatically as its superview is resized, and you’re supposed to provide one or more of these when setting a UIView’s autoresizingMask
property. The autoresizing options are listed in the documentation as follows:
enum { UIViewAutoresizingNone = 0, UIViewAutoresizingFlexibleLeftMargin = 1 << 0, UIViewAutoresizingFlexibleWidth = 1 << 1, UIViewAutoresizingFlexibleRightMargin = 1 << 2, UIViewAutoresizingFlexibleTopMargin = 1 << 3, UIViewAutoresizingFlexibleHeight = 1 << 4, UIViewAutoresizingFlexibleBottomMargin = 1 << 5 }; typedef NSUInteger UIViewAutoresizing;
The <<
symbol is the left shift operator; the right operand says how many bits to shift the left operand. So pretend that an NSUInteger is 8 bits (it isn’t, but let’s keep things simple and short). Then this enum means that the following name–value pairs are defined (using binary notation for the values):
UIViewAutoresizingNone
00000000
UIViewAutoresizingFlexibleLeftMargin
00000001
UIViewAutoresizingFlexibleWidth
00000010
UIViewAutoresizingFlexibleRightMargin
00000100
UIViewAutoresizingFlexibleTopMargin
00001000
and so on. The reason for this bit-based representation is that these values can be combined into a single value (a bitmask) that you pass to set the autoresizingMask
. All Cocoa has to do in order to understand your intentions is to look to see which bits in the value that you pass are set to 1. So, for example, 00001010
would mean that UIViewAutoresizingFlexibleTopMargin
and UIViewAutoresizingFlexibleWidth
are true (and that the others, by implication, are all false).
The question is how to form the value 00001010
in order to pass it. You could just do the math, figure out that binary 00001010
is decimal 10, and set the autoresizingMask
property to 10, but that’s not what you’re supposed to do, and it’s not a very good idea, because it’s error-prone and makes your code incomprehensible. Instead, use the bitwise-or operator to combine the desired options:
myView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
This notation works because the bitwise-or operator combines its operands by setting in the result any bits that are set in either of the operands, so 00001000 | 00000010
is 00001010
, which is just the value we’re trying to convey.
Simple assignment (K&R 2.10) is by the equal sign. But there are also compound assignment operators that combine assignment with some other operation. For example:
height *= 2; // same as saying: height = height * 2;
The ternary operator (?:
) is a way of specifying one of two values depending on a condition (K&R 2.11). The scheme is as follows:
(condition) ? exp1 : exp2
If the condition is true (see the next section for what that means), the expression exp1
is evaluated and the result is used; otherwise, the expression exp2
is evaluated and the result is used. For example, you might use the ternary operator while performing an assignment, using this schema:
myVariable = (condition) ? exp1 : exp2;
What gets assigned to myVariable
depends on the truth value of the condition. There’s nothing happening here that couldn’t be accomplished more verbosely with flow control (see the next section), but the ternary operator can greatly improve clarity, and I use it a lot.
No credit card required