我对标准6.5.4/6中的以下措辞感到困惑:
如果表达式的值用更大的范围表示,或者 精度超过强制转换命名的类型 (6.3.1.8) 所需的精度,则 强制转换指定转换,即使表达式的类型为 与命名类型相同,并删除任何额外的范围和精度。
我无法理解的是,如果命名类型和表达式的类型相同,表达式的值如何具有一些额外的范围或精度。
你能提供一个演示规则的例子吗?目前看起来有点混乱。
该标准允许以比表达式类型更高的精度计算浮点数;例如:
float f = 1.234f * 5.678f;
允许编译器将操作数转换为long double
,进行乘法运算,然后转换回float
。 这样做的基本原理是,在许多处理器上,仅使用特定的浮点寄存器大小进行计算会更快,通常人们并不关心获得精度。
这在 C17 5.2.4.2.2/9 中指定:
除了赋值和强制转换(删除所有额外的范围和精度)之外,具有浮点操作数的运算符生成的值以及受通常算术转换和浮点常量约束的值将计算为其范围和精度可能大于类型要求的格式。评估格式的使用的特点是实现定义的
FLT_EVAL_METHOD
值:
−1
不确定的;0
仅根据- 类型的范围和精度计算所有运算和常量;
1
计算浮点型和双精度型的运算和常数,评估长双精度型的范围和精度的常数;2
计算所有运算和常量,以达到长双精度类型的范围和精度。
FLT_EVAL_METHOD
的所有其他负值表征实现定义的行为。
因此,您可以检查FLT_EVAL_METHOD
以了解编译器是否可能执行此操作,但您不一定自己控制设置。
您引用的文本重申了强制转换运算符将结果转换回强制转换的类型,例如:
float f = 1.234f * 5.678f + 9.012f;
理论上可以给出比以下更准确的结果:
float f = (float)(1.234f * 5.678f) + 9.012f;