In §7.22.1.3 The strtod()
, strtof()
and strtold()
functions, the C11 standard (ISO/IEC 9899:2011) says:
The functions return the converted value, if any. If no conversion could be performed,
zero is returned. If the correct value overflows and default rounding is in effect (7.12.1),
plus or minus HUGE_VAL
, HUGE_VALF
, or HUGE_VALL
is returned (according to the
return type and sign of the value), and the value of the macro ERANGE
is stored in
errno
. If the result underflows (7.12.1), the functions return a value whose magnitude is
no greater than the smallest normalized positive number in the return type; whether
errno
acquires the value ERANGE
is implementation-defined.
The standard also notes in §5.2.4.2.2 Characteristics of floating types that IEC 60559 (IEEE 754) floating point numbers have the limit:
DBL_MIN 2.2250738585072014E-308 // decimal constant
Since 1.8011670033376514e-308 is smaller than DBL_MIN
, you get a sub-normal number, and ERANGE
is quite appropriate (but optional).
On Mac OS X 10.9.4 with GCC 4.9.1, the following program:
#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;
}
produces the output:
34: Result too large
1.8011670033376514e-308
0x01 0x00 0x00 0x00 0xA8 0xF3 0x0C 0x00
The error message is ironically wrong — the value is too small — but you can't have everything.