Chapter 8. Statements

A statement is a complete instruction to the computer. Except as indicated, statements are executed in sequence. Statements have the following form:

statement: 

expression-statement

compound-statement

selection-statement

iteration-statement

jump-statement

labeled-statement

Expression Statement

Most statements are expression statements, which have the following form:

expression-statement: 

expressionopt;

Usually expression statements are expressions evaluated for their side effects, such as assignments or function calls. A special case is the null statement, which consists of only a semicolon.

Compound Statement or Block

A compound statement (or block) groups a set of statements into a syntactic unit. The set can have its own declarations and initializers, and has the following form:

compound-statement: 

{declaration-listopt statement-listopt}

declaration-list: 

declaration

declaration-list declaration

statement-list: 

statement

statement-list statement

Declarations within compound statements have block scope. If any of the identifiers in the declaration list were previously declared, the outer declaration is hidden for the duration of the block, after which it resumes its force. In traditional C, however, function declarations always have file scope whenever they appear.

Initialization of identifiers declared within the block is restricted to those that have no linkage. Thus, the initialization of an identifier declared within the block using the extern specifier is not allowed. These initializations are performed only once, prior to the first entry into the block, for identifiers with static storage duration. For identifiers with automatic storage duration, it is performed each time the block is entered at the top. It is currently possible (but a bad practice) to transfer into a block; in that case, no initializations are performed.

Selection Statements

Selection statements include if and switch statements and have the following form:

selection-statement: 

if (expression) statement

if (expression) statement else statement

switch (expression) statement

Selection statements choose one of a set of statements to execute, based on the evaluation of the expression. The expression is referred to as the controlling expression.

if Statement

The controlling expression of an if statement must have scalar type.

For both forms of the if statement, the first statement is executed if the controlling expression evaluates to nonzero. For the second form, the second statement is executed if the controlling expression evaluates to zero. An else clause that follows multiple sequential else-less if statements is associated with the most recent if statement in the same block (that is, not in an enclosed block).

switch Statement

The controlling expression of a switch statement must have integral type. The statement is typically a compound statement, some of whose constituent statements are labeled case statements (see “Labeled Statements”). In addition, at most one labeled default statement can occur in a switch. The expression on each case label must be an integral constant expression. No two expressions on case labels in the same switch can evaluate to the same constant.

A compound statement attached to a switch can include declarations. Due to the flow of control in a switch, however, initialization of identifiers so declared are not performed if these initializers have automatic storage duration.

The integral promotions are performed on the controlling expression, and the constant expression of each case statement is converted to the promoted type. Control is transferred to the labeled case statement whose expression value matches the value of the controlling expression. If no such match occurs, control is transferred either past the end of the switch or to the labeled default statement, if one exists in the switch. Execution continues sequentially once control has been transferred. In particular, the flow of control is not altered upon encountering another case label. The switch statement is exited, however, upon encountering a break or continue statement (see “break Statement”, and “continue Statement”, respectively).

The following is a simple example of a complete switch statement:

switch (c) {
      case 'o':
          oflag = TRUE;
          break;
      case 'p':
          pflag = TRUE;
          break;
      case 'r':
          rflag = TRUE;
          break;
      default :
          (void) fprintf(stderr,
          "Unknown option\n");
          exit(2);
} 

Iteration Statements

Iteration statements execute the attached statement (called the body) repeatedly until the controlling expression evaluates to zero. In the for statement, the second expression is the controlling expression. The format is as follows:

iteration-statement: 

while (expression) statement

dostatementwhile (expression) ;

for(expressionopt ; expressionopt ; expressionopt) statement

The controlling expression must have scalar type.

The flow of control in an iteration statement can be altered by a jump statement (see “Jump Statements”).

while Statement

The controlling expression of a while statement is evaluated before each execution of the body.

do Statement

The controlling expression of a do statement is evaluated after each execution of the body.

for Statement

The for statement has the following form:

for (expressionopt ; expressionopt ; expressionopt) 

statement

The first expression specifies initialization for the loop. The second expression is the controlling expression, which is evaluated before each iteration. The third expression often specifies incrementation. It is evaluated after each iteration.

This statement is equivalent to the following:

expression-1; 

while (expression-2)

{

statement

expression-3;

}

One exception exists, however. If a continue statement (see “continue Statement”") is encountered, expression-3 of the for statement is executed prior to the next iteration.

Any or all of the expressions can be omitted. A missing expression-2 makes the implied while clause equivalent to while. Other missing expressions are simply dropped from the previous expansion.

Jump Statements

Jump statements cause unconditional transfer of control. The syntax is as follows:

jump-statement: 

gotoidentifier;

continue;

break;

return expressionopt;

goto Statement

Control can be transferred unconditionally by means of a goto statement:

goto identifier;

The identifier must name a label located in the enclosing function. If the label has not yet appeared, it is implicitly declared. (See “Labeled Statements”, for more information.)

continue Statement

The continue statement can appear only in the body of an iteration statement. It causes control to pass to the loop-continuation portion of the smallest enclosing while, do, or for statement; that is, to the end of the loop. Consider each of the following statements:

while (...)
{
..
contin: ;
}

do {
     ...
     contin: ;
} while (...) ;

for (...) {
     ...
     contin: ;
}

A continue is equivalent to gotocontin. Following the contin: is a null statement.

A goto statement must not cause a block to be entered by a jump from outside the block to a labeled statement in the block (or an enclosed block) if that block contains the declaration of a variably modified object or variably modified typedef name.

break Statement

The break statement can appear only in the body of an iteration statement or code attached to a switch statement. It transfers control to the statement immediately following the smallest enclosing iteration or switch statement, terminating its execution.

return Statement

A function returns to its caller by means of the return statement. The value of the expression is returned to the caller (after conversion to the declared type of the function), as the value of the function call expression. The return statement cannot have an expression if the type of the current function is void.

If the end of a function is reached before the execution of an explicit return, an implicit return (with no expression) is executed. If the value of the function call expression is used when none is returned, the behavior is undefined.

Labeled Statements

Labeled statements have the following syntax:

labeled-statement: 

identifier : statement

caseconstant-expression : statement

default : statement

A case or default label can appear only on statements that are part of a switch.

Any statement can have a label attached as a simple identifier. The scope of such a label is the current function. Thus, labels must be unique within a function. In traditional C, identifiers used as labels and in object declarations share a name space. Thus, use of an identifier as a label hides any declaration of that identifier in an enclosing scope. In ANSI C, identifiers used as labels are placed in a different name space from all other identifiers and do not conflict. Therefore, the following code fragment is legal in ANSI C but not in traditional C:

{
     int foo;
     foo = 1;
     ...
     goto foo;
     ...
     foo: ;
}