Void function call as expressions

Viewed 746

It's clear from the C standard that general function calls are expressions from the definition:

An expression is a sequence of operators and operands that specifies computation of a value, or that designates an object or a function, or that generates side effects, or that performs a combination thereof. The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. (6.5.1)

Since the () are operators and it returns a value, regular function calls are obviously expressions.

But those which don't return a value don't seem to fit with this definition. The function name itself does (as it designates a function), but this isn't a function call.

The standard does clearly say that a function call is an expression, and that it can return void, but this seems to conflict with the definition of an expression. What am I missing?

4 Answers

Calling a function is an expression regardless of the function's return type. C's grammar is orthogonal to its type system. They are independent pieces of the language. Grammatically func(); is an expression statement.

expression_statement
    : ';'
    | expression ';'
    ;

postfix_expression
    : primary_expression
    | postfix_expression '[' expression ']'
    | postfix_expression '(' ')'
    | postfix_expression '(' argument_expression_list ')'

There are very few things you can do with a void result. You can't assign it to a variable since void variables aren't allowed. If func()'s result is void you can use four operators:

  • Parentheses: (func())
  • Comma sequencing: func(), 42
  • Ternary operator: 42 ? func() : func().
  • Cast to void: (void) func()

You can also return a void result:

return func();

Finally, in a for(init; condition; increment) loop the three pieces are all expressions. init and increment (but not condition) can be void.

for (func(); 42; func()) { }

Few of these are useful and none are good style, but they're all legal.

Paragraph 1 of clause 6.5 was not completely thought out with regard to void. The C standard is imperfect and has a number of defects. This paragraph should be received as a general description to orient readers and is not a precise mathematical specification of what an expression is.

It is said that:

An expression is a sequence of operators and operands that

  • specifies computation of a value, or
  • that designates an object or a function or
  • that generates side effects
  • or that performs a combination thereof.

The specifies computation of a value is but one among possibilities. The void function call would be the one "that generates side effects".


Any expression in the expression statement in C is considered a void expression. C11 6.8.3 Expression and null statements p2:

  1. The expression in an expression statement is evaluated as a void expression for its side effects.153)

153) Such as assignments, and function calls which have side effects.

i.e. in the expression statement

a = 5;

a = 5 is a void expression that is evaluated for its side effects only, i.e. the assignment of value 5 into a, not for computation of a value, even though a = 5 could be used for a computation of a value in other contexts. Likewise you can write a; and it is a legal use of an expression "evaluated for its side effects", even though it has none. It does not cease to be an expression there.

The LHS of a comma operator is a void expression. A void expression can be used in ? : - then both branches will be void expressions and the entire expression in itself will be a void expression.

An expression in C can be void. Such an expression has not a value and then it cannot be assigned to an object. Moreover, any expression can be cast to void.

Related