411 REFERENCE · Wikibooks
A Little C Primer/C Control Constructs
Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.
C contains a number of looping constructs, such as the "while" loop:
/* while.c */
#include <stdio.h>
void main()
{
int test = 10;
while( test > 0 )
{
printf( "test = %d\n", test );
test = test - 2;
}
}
If "test" starts with an initial value less than or equal to 0 the "while"
loop will not execute even once. There is a variant, "do", that will always
execute at least once:
/* do.c */
#include <stdio.h>
void main()
{
int test = 10;
do
{
printf( "test = %d\n", test );
test = test - 2;
}
while( test > 0 );
}
The most common looping construct is the "for" loop, which creates a loop
much like the "while" loop but in a more compact form:
/* for.c */
#include <stdio.h>
void main()
{
int test;
for( test = 10; test > 0; test = test - 2 )
{
printf( "test = %d\n", test );
}
}
Notice that with all these loops, the initial loop statement does not end
with a ";". If a ";" was placed at the end of the "for" statement above, the
"for" statement would execute to completion, but not run any of the
statements in the body of the loop.
The "for" loop has the syntax:
for( <initialization>; <operating test>; <modifying expression> )
All the elements in parentheses are optional. A "for" loop could be run
indefinitely with:
for( ; ; )
{
...
}—although using an indefinite "while" is cleaner:
while( 1 )
{
...
}
It is possible to use multiple expressions in either the initialization or
the modifying expression with the "," operator:
/* formax.c */
#include <stdio.h>
void main()
{
int a, b;
for ( a = 256, b = 1; b < 512 ; a = a / 2, b = b * 2 )
{
printf( "a = %d b = %d\n", a, b );
}
}
The conditional tests available to C are as follows:
a == b equals
a != b not equals
a < b less than
a > b greater than
a <= b less than or equals
a >= b greater than or equals
The fact that "==" is used to perform the "equals" test, while "=" is used as
the assignment operator, often causes confusion and is a common bug in C
programming:
a == b Is "a" equal to "b"?
a = b Assign value of "b" to "a".
C also contains decision-making statements, such as "if":
/* if.c */
#include <stdio.h>
#define MISSILE 1
void fire( int weapon );
void main()
{
fire( MISSILE );
}
void fire( int weapon )
{
if( weapon == MISSILE )
{
printf( "Fired missile!\n" );
}
if( weapon != MISSILE )
{
printf( "Unknown weapon!\n");
}
}
This example can be more easily implemented using an "else" clause:
/* ifelse.c */
void fire( int weapon )
{
if( weapon == MISSILE )
{
printf( "Fired missile!\n" );
}
else
{
printf( "Unknown weapon!\n");
}
}
Since there is only one statement in each clause the curly brackets aren't
really necessary. This example would work just as well:
void fire( int weapon )
{
if( weapon == MISSILE )
printf( "Fired missile!\n" );
else
printf( "Unknown weapon!\n" );
}
However, the brackets make the structure more obvious and prevent errors if
you add statements to the conditional clauses. The compiler doesn't care one
way or another, it generates the same code.
There is no "elseif" keyword, but "if" statements can be nested:
/* nestif.c */
#include <stdio.h>
#define MISSILE 1
#define LASER 2
void fire( int weapon );
void main()
{
fire( LASER );
}
void fire( int weapon )
{
if( weapon == MISSILE )
{
printf( "Fired missile!\n" );
}
else
{
if( weapon == LASER )
{
printf( "Fired laser!\n" );
}
else
{
printf( "Unknown weapon!\n");
}
}
}
This is somewhat clumsy. The "switch" statement does a cleaner job:
/* switch.c */
void fire( int weapon )
{
switch( weapon )
{
case MISSILE:
printf( "Fired missile!\n" );
break;
case LASER:
printf( "Fired laser!\n" );
break;
default:
printf( "Unknown weapon!\n");
break;
}
}
The "switch" statement tests the value of a single variable; unlike the "if"
statement, it can't test multiple variables. The optional "default" clause
is used to handle conditions not covered by the other cases.
Each clause ends in a "break", which causes execution to break out of the
"switch". Leaving out a "break" can be another subtle error in a C program,
since if it isn't there, execution flows right through to the next clause.
However, this can be used to advantage. Suppose in our example the routine
can also be asked to fire a ROCKET, which is the same as a MISSILE:
void fire( int weapon )
{
switch( weapon )
{
case ROCKET:
case MISSILE:
printf( "Fired missile!\n" );
break;
case LASER:
printf( "Fired laser!\n" );
break;
default:
printf( "Unknown weapon!\n");
break;
}
}
The "break" statement is not specific to "switch" statements. It can be used
to break out of other control structures, though good program design tends to
avoid such improvisations:
/* break.c */
#include <stdio.h>
void main()
{
int n;
for( n = 0; n < 10; n = n + 1 )
{
if( n == 5 )
{
break; /* Punch out of loop at value 5. */
}
else
{
printf( "%d\n", n );
}
}
}
If the "for" loop were nested inside a "while" loop, a "break" out of the
"for" loop would still leave you stuck in the "while" loop. The "break"
keyword only applies to the control construct that executes it.
There is also a "continue" statement that skips to the end of the loop body
and continues with the next iteration of the loop. For example:
/* continue.c */
#include <stdio.h>
void main()
{
int n;
for( n = 0; n < 10; n = n + 1 )
{
if( n == 5 )
{
continue;
}
else
{
printf( "%d\n", n );
}
}
}
Finally, there is a "goto" statement:
goto punchout;
...
punchout:—that jumps to an arbitrary tag within a function, but the use of this
statement is generally discouraged and it is rarely seen in practice.
While these are the lot of C's true control structures, there is also a
special "conditional operator" that performs a simple conditional assignment
of the form:
if( a == 5)
{
b = -10;
}
else
{
b = 255;
}—using a much tidier, if more cryptic, format:
b = ( a == 5 ) ? -10 : 255 ;
the ?: construct is called a ternary operator—or the ternary operator—as it takes 3 arguments.