You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

C99 Section 6.8.6.4 3 states

If a return statement with an expression is executed, the value of the expression is returned to the caller as the value of the function call expression. If the expression has a type different from the return type of the function in which it appears, the value is converted as if by assignment to an object having the return type of the function. 142)

This paragraph is footnoted as follows:

142) The return statement is not an assignment. The overlap restriction of subclause 6.5.16.1 does not apply to the case of function return. The representation of floating-point values may have wider range or precision. A cast may be used to remove this extra range and precision.

Conversion as if by assignment to the type of the function is required if the return expression has a different type than the function, but not if the return expression has a wider value only because of wide evaluation. This allows seemingly inconsistent and confusing behavior. Consider

float f(float x) { return x * 0.1f; }

float g(float x) { return x * 0.1; }

Function f is allowed to return a value wider than float, but function g (which uses the wider constant) is not.

Although the current text does not require narrowing return expressions of the same type as the function, it does not clearly state what is allowed. Is it allowed to narrow the result? Is it allowed to narrow the result sometimes but not always? Is it allowed to partially narrow the result (e.g., if the ABI returns floats in double format but a float function has a float return expression evaluated to wider than double)? An aggressive implementation could argue “yes” to all these, though the resulting behavior would complicate debugging and error analysis.

Footnote 142 says a cast may be used to remove extra range and precision from the return expression. This means a predictable program must have casts on all floating-point function calls (except where the function directly feeds an operator like assignment that implies the conversion). With type-generic math (tgmath), the programmer has to reason through the tgmath resolution rules to determine which casts to apply. These are significant obstacles to writing predictable code.

  • No labels