涉及文字的比较安全吗?
Comparisons involving literals safe?
考虑代码:
#define LITERAL 1.0
int main()
{
double x = LITERAL;
if (x == LITERAL) return 1;
else return 0;
}
这是否保证 return 1
对于我们设置的任何数字双精度值 LITERAL
(不仅是 1.0
,还有任何其他双精度文字)?
编辑:为什么问题因为 "missing details" 而关闭?这是一个定义明确的 C/C++ 问题,并得到了很好的答案。不需要更多细节,这是关于这些语言如何工作的一般性问题。
首先,您必须假设一个(试图)符合附件 F 的实现,否则所有的赌注都会被取消;没有附件 F(IEEE 浮点)C 允许所有浮点结果任意伪造。
然后,根据语言规范,根据您的 C 实现对 FLT_EVAL_METHOD
的定义,是或否。
如果值为 0 或 1,则为。文字被解释为 double
,double
对象忠实地存储该值,相等运算符产生 1(真),反映了这一点。
如果值为 2,则仅当字面量是可表示的 double
的精确十进制表示形式或以足够的精度表示它与仅超过 long double
精度的字面量不同时.否则(例如,如果它类似于 0.1
),因为在 long double
中用 excess precision 解释文字,将 initialization/assignment 格式化为 double
对象将精度截断为标称 double
精度。然后保证相等比较结果为 0(假)。你可以see this in action on Compiler Explorer(注意:去掉volatile
你可以看到它优化为return一个常量0)。
为了让事情变得更复杂,GCC 默认情况下 是错误的 ,除非你使用 -std=c..
或 -fexcess-precision=standard
,而 总是这样在 C++ 模式下它是错误的,并且 clang/LLVM 总是错误的。因此,在精度过高的目标上(32 位 x86 或 m68k,唯一具有 FLT_EVAL_METHOD
而不是 0 或 1 的与现实世界相关的目标)会发生可怕的事情。要了解它们变得有多糟糕,请参阅 GCC issue 93806 和(递归地)所有 "See Also" 相关问题。
所以出于实际目的,是的,除了 32 位 x86 和 m68k 之外的所有东西,并且在正确的 C 实现中没有(但也许是,因为你的编译器可能坏了)。
考虑代码:
#define LITERAL 1.0
int main()
{
double x = LITERAL;
if (x == LITERAL) return 1;
else return 0;
}
这是否保证 return 1
对于我们设置的任何数字双精度值 LITERAL
(不仅是 1.0
,还有任何其他双精度文字)?
编辑:为什么问题因为 "missing details" 而关闭?这是一个定义明确的 C/C++ 问题,并得到了很好的答案。不需要更多细节,这是关于这些语言如何工作的一般性问题。
首先,您必须假设一个(试图)符合附件 F 的实现,否则所有的赌注都会被取消;没有附件 F(IEEE 浮点)C 允许所有浮点结果任意伪造。
然后,根据语言规范,根据您的 C 实现对 FLT_EVAL_METHOD
的定义,是或否。
如果值为 0 或 1,则为。文字被解释为 double
,double
对象忠实地存储该值,相等运算符产生 1(真),反映了这一点。
如果值为 2,则仅当字面量是可表示的 double
的精确十进制表示形式或以足够的精度表示它与仅超过 long double
精度的字面量不同时.否则(例如,如果它类似于 0.1
),因为在 long double
中用 excess precision 解释文字,将 initialization/assignment 格式化为 double
对象将精度截断为标称 double
精度。然后保证相等比较结果为 0(假)。你可以see this in action on Compiler Explorer(注意:去掉volatile
你可以看到它优化为return一个常量0)。
为了让事情变得更复杂,GCC 默认情况下 是错误的 ,除非你使用 -std=c..
或 -fexcess-precision=standard
,而 总是这样在 C++ 模式下它是错误的,并且 clang/LLVM 总是错误的。因此,在精度过高的目标上(32 位 x86 或 m68k,唯一具有 FLT_EVAL_METHOD
而不是 0 或 1 的与现实世界相关的目标)会发生可怕的事情。要了解它们变得有多糟糕,请参阅 GCC issue 93806 和(递归地)所有 "See Also" 相关问题。
所以出于实际目的,是的,除了 32 位 x86 和 m68k 之外的所有东西,并且在正确的 C 实现中没有(但也许是,因为你的编译器可能坏了)。