Expressions as Statements in C

In the C language, there is a close relationship between expressions and statements.

In particular, in C it is possible to use an expression wherever a statement is expected. In this lesson we will explore this concept in depth. We will also delve into the concept of side effects and the behavior of compilers in the presence of expressions used as statements.

Expressions as Statements

The C language, and all languages derived from it such as C++, allow the use of expressions as statements.

In other words, any expression—regardless of its complexity or the type of value it returns—can be used as a statement by placing a semicolon at the end.

For example, the following line of code is an expression that returns the value 5, and can be used as a statement:

2 + 3;

What happens when this statement is executed is that the result of the expression is calculated, but it is not stored in any variable and is not used in any way. The result is discarded.

Obviously, an expression whose result is discarded doesn't make much sense—unless it has side effects.

For example, take the following statement:

x++;

This statement increments the value of the variable x by 1 and returns the incremented value. Even though the result of the expression is discarded, the side effect is that the value of x is incremented by 1. So the variable x is effectively modified.

Let’s take another example:

x = 5;

In this case, it is an assignment expression. So what happens is that the value 5 is assigned to the variable x, and the result of the expression is the assigned value, which is 5. Again, the result of the expression is discarded, but the side effect is that the value of x is modified.

One last example:

x * 2 + y;

In this case, there are no side effects. The expression does not modify any value, and the result is discarded. So in this case, the statement serves no purpose.

Definition

Expressions as Statements

In the C language, any expression can be used as a statement.

The syntax is as follows:

expression;

When an expression is used as a statement, the result of the expression is calculated, but discarded.

The statement may have side effects, such as modifying variables. Otherwise, its execution has no effect.

Side Effects and Compilers

Including an expression as a statement in a C program can be useful to exploit the side effects it produces.

However, if it does not have any side effects, its inclusion in the code can be considered a programming error. In fact, although it generates machine code that is actually executed, the result of the expression is discarded, so the presence of the statement unnecessarily complicates the code.

For this reason, many compilers—including gcc—emit a warning when an expression is used as a statement.

For example, compiling our programs with gcc and the -Wunused-value option:

gcc -Wunused-value -o program program.c

will produce a warning for each expression used as a statement that has no side effects.

program.c: In function 'main':
program.c:5:2: warning: statement with no effect [-Wunused-value]
  5 | 2 + 3;
    | ^~~~~~

Moreover, if we enable optimizations with the -O2 option, the compiler may completely remove the statement from the generated machine code, as it has no effect. This type of optimization is known as Dead Code Elimination (DCE for short).

Through DCE, the compiler is able to detect and remove from the machine code all statements that have no effect, improving the performance of the program.

But be careful. As we will see later in upcoming lessons, it does not always make sense to eliminate code that has no side effects. It may seem counterintuitive, but there are special cases in which removing code with no side effects can lead to unexpected results.

In Summary

In this lesson, we have seen that in the C language it is possible to use expressions as statements. This means that any expression—regardless of its complexity or the type of data it returns—can be used as a statement by placing a semicolon at the end.

We have seen that an expression used as a statement may have side effects, such as modifying variables. Otherwise, the statement has no effect.

Lastly, we saw that using expressions as statements can unnecessarily complicate the code, and that many compilers emit a warning when an expression with no side effects is used as a statement.