这是我的测试代码:
errno = 0;
d = strtod("1.8011670033376514e-308", NULL);通过这段代码,我得到了d == 1.8011670033376514e-308和errno == ERANGE。
来自strtod(3):
如果正确的值会导致溢出,则返回正负
HUGE_VAL(HUGE_VALF,HUGE_VALL) (根据值的符号),ERANGE存储在errno中。如果正确的值会导致下溢,则返回零并将ERANGE存储在errno中。
所以,在我看来,要么errno应该是零(没有错误),要么d应该是零(下流量)。
这是个窃听器还是我漏掉了什么?这种情况发生在许多不同版本的eglibc和gcc身上。
发布于 2014-08-26 06:28:33
在第7.22.1.3节“strtod()__、strtof()和strtold()函数”中,C11标准(ISO/IEC 9899:2011)规定:
函数返回转换后的值(如果有的话)。如果不能执行转换,则返回零。如果正确的值溢出和默认舍入有效(7.12.1),则返回正负
HUGE_VAL、HUGE_VALF或HUGE_VALL(根据值的返回类型和符号),并将宏ERANGE的值存储在errno中。如果结果下垂(7.12.1),则函数返回一个值,其大小不大于返回类型中最小的归一化正数;errno是否获得ERANGE值是实现定义的。
该标准还在第5.2.4.2.2节中指出,IEC 60559 (IEEE 754)浮点数有以下限制:
DBL_MIN 2.2250738585072014E-308 //十进制常数
因为1.8011670033376514e-308比DBL_MIN小,所以得到一个低于正常值的数字,而ERANGE是非常合适的(但可选)。
在Mac 10.9.4和GCC 4.9.1上,程序如下:
#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具有讽刺意味的是,错误信息是错误的--其值太小--但您不可能拥有所有的东西。
发布于 2014-08-26 06:11:38
如果strtod()返回一个非零值(即非+/- HUGE_VAL),则调用已成功(根据您引用的手册页)。
引用errno.h的手册页
<errno.h>头文件定义了整数变量errno,该变量由系统调用和一些库函数在发生错误时设置,以指示出了什么问题。只有当调用的返回值指示错误(即大多数系统调用的-1;大多数库函数的-1或NULL);允许成功的函数更改时,它的值才有意义。
因此,只有当函数的返回值实际返回一个指示发生错误的值时,才能检查errno是否存在错误。
对errno的更完整的解释(以及它与strtod()的关系的解释)可以找到on another StackExchange。
发布于 2014-08-26 06:30:19
根据strtod(),代码的行为是正确的
如果正确的值会导致下溢,则返回值的大小不大于返回类型中最小的归一化正数,并将errno设置为ERANGE。
我想说的是,您所看到的是Linux手册中的一个详细错误。
https://stackoverflow.com/questions/25498987
复制相似问题