我将引用N1570,但是C11标准具有类似的措辞:
fpclassify
宏将其参数值分类为NaN,无限,普通, 次普通,零或归类为另一个实现定义的类别。首先,争论 以比其语义类型更宽的格式表示的内容转换为其语义类型。 然后根据参数的类型进行分类。
(我的重点)
还有一个脚注:
由于表达式可以比其类型具有更多的范围和精度进行评估,因此对于 知道分类所基于的类型。例如,正常的
long double
值可能 转换为double
时变为非正规,转换为float
时为零。
将参数“转换为其语义类型”是什么意思。在任何明显的地方都没有“语义类型”的定义。
我的理解是,所有多余的精度都将被删除,就像将表达式的值存储到变量float
,double
或long double
一样,导致精度值程序员的期望。在这种情况下,在左值上使用fpclassify()
和朋友将导致非优化编译器不需要进行任何转换。我是对的,还是这些功能没有广告宣传的有用?
(此问题来自对Code Review answer的评论)
答案 0 :(得分:3)
语义类型只是C标准其他地方描述的表达式类型,而无视允许以超高的精度和范围表示值的事实。同样,如果第5.2.4.2.2条第9款(表示浮点值可能会以超出范围和精度的方式进行评估)不在标准范围内,则语义类型就是表达式的类型。
将参数转换为语义类型意味着放弃多余的精度和范围(通过使用对该操作有效的舍入规则将值舍入为语义类型)。
关于您的假设,即对左值应用fpclassify
不需要任何转换(因为存储在由左值指定的对象中的值在分配时必须已经转换为其语义类型),我是不确定是否正式成立。当然,当通过赋值更新对象的值时,5.2.4.2.2 9要求删除多余的范围和精度。但是请考虑修改值的其他方法,例如后缀增量运算符。那算作作业吗?它在6.5.2.4 2中的规范要求查看化合物分配的讨论以获取有关其转换和效果的信息。那有点模糊。人们将不得不考虑所有可能的修改对象的方式,并评估C标准对它们的评价。