After reading answers about the topic of control reaches end of non-void functions I didn't see any answer adressing specifically the the case of exiting a non-void function with an empty return
statement:
int return_integer() { return; } // empty return in non-void function
What I've found so far in the C standard is:
6.8.6.4 The return statement
Constraints
- A
return
statement with an expression shall not appear in a function whose return type isvoid
. Areturn
statement without an expression shall only appear in a function whose return type isvoid
.
The standard quote states what should we do with our return
statements for void
and non-void
functions, what happens when we ignore the constraint is mentioned in other part of the document:
6.9.1 Function definitions
- If the
}
that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.
Previous standard quote states that UB happens if we use the returned value from a function which ends after reaching the closing curly braces (}
), so we have UB in the code below:
int UB(int x) { if (x) return x; }
printf("%d", UB(1)); // Correct
printf("%d", UB(0)); // Undefined behavior
In the UB(1)
call the function returns 1
through the return x;
instruction under the if (x)
; in the UB(0)
call the if (x)
condition is not passed so function ends reaching }
, to use the return value in this case is UB (but isn't in UB(1)
). But, what happens in this case?
int UB(int x) { if (x) return; } // empty return statement
printf("%d", UB(1)); // Undefined behavior?
printf("%d", UB(0)); // Undefined behavior
In the code above, the call UB(1)
does not meet the §6.9.1/12
requirements to lead to UB because the function ends without reaching }
and also does not return any value.
In which part of the C standard is this situation described?
In a non-void function you have to return something. Usually a nullptr signals an error. You could return an optional pointer, but you'd still be returning something.
In functions that have non-void return types (dont worry, we'll cover "void" later), a value is returned by the function when we call it. We know a function has a non-void return type by looking for a return type in the first line of the function definition or a return statement in the body of the function.
If control reaches the closing curly brace ( } ) of a non- void function without evaluating a return statement, using the return value of the function call is undefined behavior.
No; that is not needed. You only need to write return; if you want to return early and skip the rest of the function.
int UB(int x) { if (x) return; }
This is not even undefined behavior, it is a constraint violation. The cited text
A return statement without an expression shall only appear in a function whose return type is void
from 6.8.6.4 is normative, meaning the compiler is not allowed to let it slip without giving a diagnostic message. If it compiles without giving a diagnostic, the compiler is not a conforming implementation (doesn't follow the language standard).
In plain English this means: that code should not even compile.
Now if the compiler does produce a binary executable even if the code had constraint violations, all bets are off. It is no longer a C program, but some non-standard one, with no guaranteed behavior by any language standard.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With