C, Ocean Edition I

6.8 Statements and Blocks

Clause
6.8
ISO C99 mapping
6.8
Status
Normative

6.8.0 General

statement:
	labeled-statement
	compound-statement
	expression-statement
	selection-statement
	iteration-statement
	jump-statement

A statement specifies an action to be performed. Statements execute in the order written, except where a jump statement or a selection statement directs otherwise.

Every full expression in a statement is evaluated completely, in the order clause 6.5.0.1 defines, before the next statement begins.

ISO C99 mapping: 6.8.


6.8.1 Labeled Statements

labeled-statement:
	identifier : statement
	case constant-expression : statement
	default : statement

Constraints.

A case or default label shall appear only within a switch statement. A switch statement shall have at most one default label, and shall not have two case labels with the same value.

An identifier label shall be unique within the function that contains it.

Semantics.

A label declares a destination. Labels have function scope, so a label is visible throughout the function that contains it, including at points before the label appears. See clause 6.2.1.

A label does not alter the flow of control by itself. Execution reaching a labeled statement executes the statement.

An implementation should diagnose a label that is never the target of any jump.

ISO C99 mapping: 6.8.1.


6.8.2 Compound Statements

compound-statement:
	{ block-item-list-opt }

block-item:
	declaration
	statement

A block introduces a nested scope. Declarations and statements may be interleaved freely, so an object may be declared at the point where it is first needed.

An object declared in a block without static or extern has automatic storage duration. Its lifetime begins when the declaration is reached and ends when the block exits by any path, including by break, continue, return, or goto.

An object declared in a block with static has static storage duration and is initialized once, before program startup, under clause 6.7.9.1.

Re-entering a block, including through recursion, creates new automatic objects. Each is default-initialized or explicitly initialized on entry, under clause 6.7.9.2.

ISO C99 mapping: 6.8.2.


6.8.3 Expression and Null Statements

expression-statement:
	expression-opt ;

An expression statement evaluates its expression and discards the result.

A statement consisting of a semicolon alone is a null statement, which does nothing. It is useful as the body of a loop whose work is in its controlling parts.

Diagnostics. An implementation should diagnose an expression statement whose expression has no effect, and should diagnose a null statement that appears immediately after the closing parenthesis of an if, while, or for header, since that is a common typing accident:

if (ready);       /* the body is the null statement */
{
	start();      /* this block always runs */
}

ISO C99 mapping: 6.8.3.


6.8.4 Selection Statements

selection-statement:
	if ( expression ) statement
	if ( expression ) statement else statement
	switch ( expression ) statement

6.8.4.1 The if statement

Constraints.

The controlling expression shall have scalar type.

Semantics.

The controlling expression is evaluated once. If it does not compare equal to zero, the first substatement executes. Otherwise the else substatement executes, if there is one.

if (ready)
{
	start();
}
else
{
	stop();
}

An else associates with the nearest preceding if that does not already have one. An implementation should diagnose an else whose indentation disagrees with its association.

Conditions consume scalar values directly:

if (count)
{
	...
}

No separate Boolean-only condition syntax exists. See clause 6.5.0.5.

ISO C99 mapping: 6.8.4.1.

6.8.4.2 The switch statement

Constraints.

The controlling expression shall have integer type or enumerated type.

Each case label shall be an integer constant expression whose value is representable in the type of the controlling expression after the integer promotions.

Two case labels in the same switch shall not have the same value after conversion.

Semantics.

The controlling expression is evaluated once, and the integer promotions are applied. Control transfers to the case label whose value equals the result, or to the default label if there is no match, or past the end of the switch body if there is no match and no default.

switch (value)
{
	case 1:
		prepare();
		break;

	default:
		report();
		break;
}

A declaration in the body of a switch that is jumped over is subject to clause 6.8.6.1.

Fallthrough.

Execution continues from one case group into the next unless a jump statement prevents it. Fallthrough remains legal:

switch (mode)
{
	case 1:
		prepare();

	case 2:
		execute();
		break;
}

Diagnostics. An implementation shall diagnose, by default, a fallthrough from a nonempty case group into another labeled group. The diagnostic is a warning and does not change the meaning of the program.

The edition does not introduce a mandatory keyword to preserve a behavior that already works. A program that wants fallthrough writes a comment, or uses whatever suppression spelling the implementation documents, and the implementation shall provide one. See behavior.md section 93.

An implementation should also diagnose a switch over an enumerated type that omits a named enumerator and has no default label.

ISO C99 mapping: 6.8.4.2.


6.8.5 Iteration Statements

iteration-statement:
	while ( expression ) statement
	do statement while ( expression ) ;
	for ( expression-opt ; expression-opt ; expression-opt ) statement
	for ( declaration expression-opt ; expression-opt ) statement

Constraints.

The controlling expression shall have scalar type.

A declaration in the first clause of a for statement shall declare only objects with automatic storage duration, and shall not declare a static object, a typedef, or a tag.

6.8.5.1 The while statement

The controlling expression is evaluated before each execution of the body. The body executes while the expression does not compare equal to zero.

while (condition)
{
	body();
}

6.8.5.2 The do statement

The body executes, then the controlling expression is evaluated. The body executes again while the expression does not compare equal to zero. The body therefore executes at least once.

do
{
	body();
}
while (condition);

6.8.5.3 The for statement

for (init; condition; step)
{
	body();
}

is equivalent to:

init

while (condition)
{
	body
	step
}

with two additions. An object declared in init has a scope that ends with the for statement. A continue inside the body transfers to step rather than to condition.

An omitted condition is replaced by a nonzero constant, so for (;;) loops until a jump leaves it.

for (int i = 0; i < count; i++)
{
	process(i);
}

6.8.5.4 Loop termination

An implementation shall not assume that a loop terminates.

A loop whose controlling expression is not a constant, and whose body contains no jump out of the loop and no effect, may still be required to run forever, and an implementation shall not delete it or transform the program on the assumption that it exits. See clause 4.7.

Difference: ISO C99 and later standards permit an implementation to assume termination for certain loops. Ocean Edition I does not, because a program's meaning comes from the language rather than from the optimizer's convenience.

ISO C99 mapping: 6.8.5.


6.8.6 Jump Statements

jump-statement:
	goto identifier ;
	continue ;
	break ;
	return expression-opt ;

6.8.6.1 The goto statement

goto transfers control to the labeled statement named by its identifier, within the same function.

goto cleanup;

Constraints.

The identifier shall name a label in the enclosing function.

A goto shall not jump into the scope of an object with automatic storage duration in a way that would bypass that object's initialization. Jumping forward past a declaration and then using the object is a constraint violation.

Semantics.

Jumping out of a block ends the lifetime of every automatic object in the blocks being left.

Jumping backward to a point before a declaration ends the lifetime of the object and begins a new one when the declaration is reached again, with initialization performed again.

goto is primitive control flow, and it is retained. It is often the clearest expression of a cleanup path, of a parser state machine, of low-level recovery, and of resource unwinding in manual code. Removing it would be language fashion rather than semantic normalization. See syntax.md section 48.

static int open_all(struct Session *session)
{
	if (open_socket(session) != 0)
	{
		goto fail;
	}

	if (open_log(session) != 0)
	{
		goto close_socket;
	}

	return 0;

close_socket:
	close_socket(session);

fail:
	return -1;
}

6.8.6.2 The continue statement

continue shall appear within a loop body. It transfers control to the loop's continuation point:

It affects the innermost enclosing loop. A switch does not capture continue.

6.8.6.3 The break statement

break shall appear within a loop body or within a switch body. It terminates the innermost enclosing loop or switch.

6.8.6.4 The return statement

Constraints.

A return with an expression shall not appear in a function whose return type is void.

A return without an expression shall not appear in a function whose return type is not void.

Semantics.

return terminates the current function and transfers control to the caller. The expression, if present, is converted as if by assignment to the return type, and becomes the value of the call.

The lifetimes of the function's automatic objects end. Returning a pointer to such an object produces a pointer that is invalid on arrival, and an implementation shall diagnose that when it is evident:

int *broken(void)
{
	int value = 10;
	return &value;      /* diagnosed */
}

Falling off the end.

Reaching the closing brace of a function whose return type is not void, without executing a return, is invalid.

The single exception is main, where reaching the closing brace is equivalent to return 0;. See clause 5.1.2.2 and behavior.md section 40.

Difference: ISO C99 makes falling off the end of a non-void function undefined only if the caller uses the value. Ocean Edition I makes it an error, because a function that promises a value and does not produce one has no defensible meaning.

ISO C99 mapping: 6.8.6.