Previous | Table of Contents | Next |
An if statement arranges that a subsidiary statement (or block of statements) is executed or not executed, depending on some condition. The syntax is simple:
if(n > 0) average = sum / n;
If the condition in the parentheses is true (nonzero), the statement is executed. If the condition is false, the statement is skipped; execution continues with the following statement (if any).
Optionally, an if statement may include an else clause, containing a statement to be executed if the condition is not true:
if(n > 0) average = sum / n; else average = 0;
If n is greater than 0, the average is set to the quotient sum / n; otherwise, the average is set to 0. In either case, execution continues with the statement(s) further down.
When several statements are to be executed or not executed together, they can be enclosed in braces to form a block statement:
if(a > b) { t = a; a = b; b = t; }
Now, if the condition is true, all three statements are executed; if it is false, all three are skipped. (The result of this example is that a and b are swapped, if necessary, to ensure that b is greater than or equal to a.) Of course, a block statement may appear in the else clause as well:
if(n > 0) average = sum / n; else { printf(n is 0!\n); average = 0; }
Syntactically, both the if clause and the else clause are statements; a block is permissible because, syntactically, a block is a statement.
Blocks are, of course, typically indented from the left margin to make their structure more visually apparent, although it is important to remember that the compiler ignores this indentation (because C is a free-form language). Many styles of indentation and brace placement have been devised, and although it is impossible to prescribe one as best, there is some value in consistency. (The indentation style used in this chapter is representative but is neither the most nor the least popular of the common styles.)
if statements can (just like all of Cs statements) be nested arbitrarily. For example, this fragment prints a rough indication of a direction of travel, assuming that y represents the northward component and x the eastward component:
if(x > 0) if(y > 0) printf(northeast); else printf(southeast); else if(y > 0) printf(northwest); else printf(southwest);
(Obviously, an improved version would handle the cases of x == 0 and y == 0.) However, bushy if/else trees like this one can become unreadable because it becomes increasingly difficult to match up the elses correctly. Comments can help, but it is worthwhile to seek cleaner alternatives (such as table lookup) when a large, complicated if/then structure becomes unwieldy.
Another arrangement (and one much easier to read than a bushy tree) is a cascading chain of ifs and elses:
if(T < 32) printf(ice); else if(T < 212) printf(water); else printf(steam);
The sequence reads (and executes) naturally: The conditions are tested in order, and the code associated with the first matching condition is executed. (After a matching condition is found, we know that all following branches are skipped.)
Caution is necessary, however, when if statements are nested in yet another way. Consider the following code:
if(n >= 0) if(n > 0) average = sum / n; else printf(n is negative!\n);
Which of the two if clauses should the lone else clause be paired with? The indentation (and the wording in the printf call) suggests that the last message is to be printed if n is not greater than or equal to 0. This code, however, is an example of the dangling else problem. In C, as in most languages, the rule is that an else clause is always associated with the nearest if. (Once again, the indentation is immaterial.) In other words, the compiler interprets the code as if it had been written
if(n >= 0) { if(n > 0) average = sum / n; else printf(n is negative!\n); }
and the code thus interpreted does not have the desired effect. Explicit braces can, however, always be used to make the programmers intentions explicit:
if(n >= 0) { if(n > 0) average = sum / n; } else printf(n is negative!\n);
As a general rule, it is best to use explicit braces when the body of an if statement (or other control-flow construct) is any more complicated than a single, simple statement. (Some programmers prefer to use explicit blocks in all control-flow constructs.)
Previous | Table of Contents | Next |