新标准 C(ISO/IEC 9899:2023,又名 C23)
在附件 H 中定义了一些
与实数和复数算术相关的宏和类型,
并符合 ISO/IEC 60559 标准(浮点算术)。
根据 H.1 小节,存在三个
实现定义的宏来测试
与附件 H 定义的一致性。
__STDC_IEC_60559_TYPES__
__STDC_IEC_60559_BFP__
__STDC_IEC_60559_DFP__
此外,要“激活”关联的宏和类型,
用户必须定义宏:
__STDC_WANT_IEC_60559_TYPES_EXT__
该标准的措辞在几个细节上很明确:
- 如果
__STDC_IEC_60559_BFP__
是由编译器定义的,则意味着_FloatN
,_FloatN_t
和其他_FloatN*
类型也已定义。 - 如果
__STDC_IEC_60559_DFP__
是由编译器定义的,则意味着_DecimalN
,_DecimalN_t
和其他_DecimalN*
类型也已定义。 __STDC_IEC_60559_TYPES__
无论哪种情况,都会定义宏。- 如果定义了宏
__STDC_IEC_60559_TYPES__
,则意味着至少定义了一个__STDC_IEC_60559_BFP__
或(或两者)宏。__STDC_IEC_60559_DFP__
在 H.11 小节中,类型long_double_t
被添加到 中<math.h>
。
long_double_t
但是,我无法推断在哪些条件下可以确保给定实现中的存在。
问题:
如果__STDC_IEC_60559_TYPES__
已定义,是否足以确定long_double_t
也在 中定义<math.h>
?
我的怀疑来自以下可能出现的特殊情况:
__STDC_IEC_60559_TYPES__
和__STDC_IEC_60559_DFP__
已定义,但__STDC_IEC_60559_BFP__
未定义。
在本例中,定义了十进制类型。
但是,long_double_t
不是十进制类型。
子问题:
宏是否__STDC_IEC_60559_BFP__
需要存在才能确保存在long_double_t
?
评论:
正如 @John Bollinger 在他的回答中解释的那样,和/或宏的
存在
仅确保和存在于 的某些小值。
(我知道这个细节,但我的解释不是最好的。)*BFP__
*DFP__
_FloatN
_DecimalN
N
TL;DR:依赖一致实现提供的最低基础
long_double_t
是它定义了宏__STDC_IEC_60559_TYPES__
到202311L
.但是,翻译单元还必须
__STDC_WANT_IEC_60559_TYPES_EXT__
在第一次包含 math.h 之前定义(任何内容),以便实际公开该定义。(C23 H.8/1)显然不是那么清楚。
作为初步问题,规范说
如果实现没有定义
__STDC_IEC_60559_TYPES__
该特定值(即使它们将其定义为其他值),则必须理解这一点,以减轻实现与附件中任何内容的一致性。这是一种有意的向前兼容性措施。该规范继续说道:
__STDC_IEC_60559_TYPES__
请注意,根据前面的内容,除非精确定义为,否则该规定或附件中的其他任何内容均不适用202311L
。否则,就附录 H(C23)而言,所有的赌注都是错误的。例如,一个没有定义__STDC_IEC_60559_TYPES__
任何内容并且没有定义__STDC_IEC_60559_BFP__
或 的__STDC_IEC_60559_DFP__
实现不会因此而失败。不完全是。该规范没有将任何需求与
__STDC_IEC_60559_BFP__
单独定义的实现相关联。除了__STDC_IEC_60559_TYPES__
上面讨论的 定义的一般门控之外,规范还明确限制了该领域中定义的后一个宏的一些特定规定。当满足所有这些条件时,一致的实现会提供类型
_Float32
和_Float64
,并且它们分别相当于float
和double
。此外,在这些情况下,如果long double
对应于某些宽度N大于 64 的 ISO 60559 二进制交换格式之一,则该实现会提供相应的_FloatN
类型作为 的等效类型long double
。其他_FloatN
类型也是允许的,但不是必需的,并且它们的集合是实现定义的。(H.2.1/4)_FloatN_t
其提供的每种类型的 math.h 中都提供了一个遵守本附件规定的一致实现_FloatN
。同样,实施不受附件中任何内容的约束,除非它们进行了
__STDC_IEC_60559_TYPES__
适当的定义。在这种情况下,__STDC_IEC_60559_DFP__
被定义意味着提供了_Decimal32
、_Decimal64
、 和。_Decimal128
明确允许附加_DecimalN
类型,并且此类附加类型的集合是实现定义的。当附件的规定完全适用时,math.h 将提供
_DecimalN_t
与_DecimalN
实现定义的每一个相对应的。不,没有这样的要求。逻辑是相反的。
__STDC_IEC_60559_TYPES__
正如已经讨论过的,除非适当定义,否则附件 H 均不适用。如果是,那么至少还必须定义其他两个宏之一,但其中一个定义的宏并不是得出有关 的任何结论的基础__STDC_IEC_60559_TYPES__
。更具体地说,这仅适用
__STDC_IEC_60559_TYPES__
于精确定义为 的情况202311L
。__STDC_IEC_60559_TYPES__
准确定义宏202311L
足以确保其long_double_t
在实现中可用。附件没有对此提出任何附加条件。然而,该计划确实需要选择加入。C23 H.8/1:你写了:
真的。
谁说?C23 6.2.6.1/1:
该子条款没有定义任何 FP 类型的表示。
不要求 或
long double
是long_double_t
二进制类型。似乎甚至没有要求这两种类型是等效的,尽管我希望这是实现质量的问题。long_double_t
但即使是二进制类型也没有问题。__STDC_IEC_60559_BFP__
未定义并不意味着该实现不提供任何二进制 FP 类型。这仅意味着该实现拒绝承诺其符合附件 H 有关二进制 FP 类型的所有规定。否。H.11/6 指定
long_double_t
可从 math.h 获得,但须按照上面讨论的程序选择加入,并且除了以附件中的所有内容__STDC_IEC_60559_TYPES__
为条件的相同功能测试宏之外,不以任何其他方式为条件。因此,如果一致的实现定义为,则其 math.h 定义为那些选择加入的程序。__STDC_IEC_60559_TYPES__
202311L
long_double_t