【发布时间】:2017-01-09 00:18:34
【问题描述】:
在 Visual Studio 2013 中,我有以下测试代码:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ( int argc, const char* argv[])
{
static const char* floatStr = "3.40282346638528859811704183485E+39";
static const char* doubleStr = "1.79769313486231570814527423732E+309";
char* end;
float floatVal = 42.0f;
double doubleVal = 42.0;
errno = 0;
floatVal = strtof(floatStr, &end);
printf("Conversion of '%s':\nfloatVal=%f\nerrno='%s'\n",
floatStr,
floatVal,
strerror(errno));
errno = 0;
doubleVal = strtod(doubleStr, &end);
printf("Conversion of '%s':\ndoubleVal=%f\nerrno='%s'\n",
doubleStr,
doubleVal,
strerror(errno));
return 0;
}
目的是显示在非常大(溢出)输入上使用 strtof() 和 strtod() 函数时观察到的行为。
我发现 strtof() 函数会将浮点值设置为 +INF,但不会设置 ERANGE errno。然而,strtod() 函数将 double 值设置为 +INF 并设置 ERANGE errno:
Conversion of '3.40282346638528859811704183485E+39':
floatVal=1.#INF00
errno='No error'
Conversion of '1.79769313486231570814527423732E+309':
doubleVal=1.#INF00
errno='Result too large'
这种行为是预期的,还是特定于实现的细微差别?
旁注:在我看来,strtof() 可能正在调用 strtod() 并且在从 double 转换为 float 产生 +INF 结果后没有正确设置 errno?
【问题讨论】:
-
MSVC 2015 在这两种情况下都给出了 errno='Result too large'。必须是已修复的错误。
-
您可以检查您的
strtof函数是否通过调用strtod来实现,方法是使用strtof解析一个字符串,例如"1.01161128282547"。当这个十进制表示被解析为double并四舍五入到最接近的float时,它产生的结果与直接将字符串解析为float(“双舍入”)不同。由于这个原因,以这种方式实现的strtof函数质量很差,即使它正确处理溢出也是如此。质量strtof产生浮动1.01161134f。一个可怜的strtof产生1.01161122f。 -
@WeatherVane 我会在 VS2015 中尝试,然后标记答案
-
@PascalCuoq 对未来访客的宝贵观察,谢谢!
标签: c string floating-point errno