strtod下溢,返回值!= 0

时间:2014-08-26 05:54:36

标签: c strtod

这是我的测试代码:

errno = 0;
d = strtod("1.8011670033376514e-308", NULL);

使用此代码,我得到d == 1.8011670033376514e-308errno == ERANGE

来自strtod(3):

  

如果正确的值会导致溢出,则返回正负HUGE_VALHUGE_VALFHUGE_VALL)(根据值的符号)和ERANGE存储在errno中。如果正确的值会导致下溢,则返回零,并ERANGE存储errno

所以,在我看来,errno应为零(无错误)或d应为零(下溢)。

这是一个错误,还是我错过了什么?对于许多不同版本的eglibc和gcc,会发生这种情况。

3 个答案:

答案 0 :(得分:9)

在§7.22.1.3 strtod()strtof()strtold()函数中,C11标准(ISO / IEC 9899:2011)说:

  

函数返回转换后的值(如果有)。如果无法执行转换,   返回零。如果正确的值溢出且默认舍入生效(7.12.1),   返回正负HUGE_VALHUGE_VALFHUGE_VALL(根据   返回类型和值的符号),并存储宏ERANGE的值   errno。如果结果下溢(7.12.1),则函数返回幅度为的值   不大于返回类型中最小的归一化正数;是否   errno获取值ERANGE是实现定义的。

该标准还在§5.2.4.2.2浮动类型的特性中注明了IEC 60559(IEEE 754)浮点数具有限制:

DBL_MIN 2.2250738585072014E-308 // decimal constant

由于1.8011670033376514e-308小于DBL_MIN,因此您会得到一个次正常的数字,ERANGE非常合适(但可选)。

在带有GCC 4.9.1的Mac OS X 10.9.4上,以下程序:

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char *end;
    errno = 0;
    double d = strtod("1.8011670033376514e-308", &end);
    if (errno != 0)
    {
        int errnum = errno;
        printf("%d: %s\n", errnum, strerror(errnum));
    }
    printf("%24.16e\n", d);
    unsigned char *p = (unsigned char *)&d;
    const char *pad = "";
    for (size_t i = 0; i < sizeof(double); i++)
    {
        printf("%s0x%.2X", pad, *p++);
        pad = " ";
    }
    putchar('\n');
    return 0;
}

产生输出:

34: Result too large
 1.8011670033376514e-308
0x01 0x00 0x00 0x00 0xA8 0xF3 0x0C 0x00

错误信息具有讽刺意味的错误 - 价值太小 - 但你无法拥有一切。

答案 1 :(得分:3)

代码的行为符合The Open Group's POSIX specification of strtod()

  

如果正确的值会导致下溢,则返回一个大小不大于返回类型中最小归一化正数的值,并将errno设置为[ERANGE]。

我在Linux联机帮助页中说出你所看到的是一个错误。

答案 2 :(得分:2)

如果strtod()返回非零值(不是+/- HUGE_VAL),则调用成功(根据您引用的手册页)。

请参阅errno.h的手册页:

  

<errno.h>头文件定义整数变量errno,其中          由系统调用和一些库函数设置          错误表明出了什么问题。它的价值只是重要的          当呼叫的返回值表示错误(即-1时          大多数系统调用;来自大多数图书馆功能的-1NULL;的一          成功的功能可以更改errno

因此,如果函数的返回值实际返回表示发生错误的值,则只能检查errno是否有错误。

可以找到errno的更完整说明(及其与strtod()的关系的解释)on another StackExchange