St.Antario
St.Antario

Reputation: 27435

Cast-expression semantic in C

I was confused by the following wording in the Standard 6.5.4/6:

If the value of the expression is represented with greater range or precision than required by the type named by the cast (6.3.1.8), then the cast specifies a conversion even if the type of the expression is the same as the named type and removes any extra range and precision.

The thing that I cannot understand is if the named type and the type of the expression is the same how can the value of the expression have some extra range or precision.

Can you provide an example demonstrating the rule? For now it looks a bit confusing.

Upvotes: 3

Views: 234

Answers (1)

M.M
M.M

Reputation: 141638

The standard permits floating-point to be computed in higher accuracy than the type of the expression; for example:

float f = 1.234f * 5.678f;

The compiler is allowed to convert the operands to long double, do the multiplication, and then convert back to float. The rationale for this is that on many processors it's faster to just use a particular floating point register size for computations and usually people don't care about gaining precision.

This is specified in C17 5.2.4.2.2/9:

Except for assignment and cast (which remove all extra range and precision), the values yielded by operators with floating operands and values subject to the usual arithmetic conversions and of floating constants are evaluated to a format whose range and precision may be greater than required by the type. The use of evaluation formats is characterized by the implementation-defined value of FLT_EVAL_METHOD:

  • −1 indeterminable;
  • 0 evaluate all operations and constants just to the range and precision of the type;
  • 1 evaluate operations and constants of type float and double to the range and precision of the double type, evaluate long double operations and constants to the range and precision of the long double type;
  • 2 evaluate all operations and constants to the range and precision of the long double type.

All other negative values for FLT_EVAL_METHOD characterize implementation-defined behavior.

So you can inspect FLT_EVAL_METHOD to find out whether the compiler might do this, but you can't necessarily control the setting yourself.


The text you quote is reaffirming that the cast operator converts the result back to the type of the cast, e.g.:

float f = 1.234f * 5.678f + 9.012f;

could theoretically give a more accurate result than:

float f = (float)(1.234f * 5.678f) + 9.012f;

Upvotes: 4

Related Questions