C strtod下溢,返回值!=0
以下是我的测试代码:C strtod下溢,返回值!=0,c,strtod,C,Strtod,以下是我的测试代码: errno = 0; d = strtod("1.8011670033376514e-308", NULL); 使用此代码,我得到d==1.8011670033376514e-308和errno==ERANGE 来自斯特罗德(3): 如果正确的值会导致溢出,则返回加号或减号巨值(巨值,巨值)(根据值的符号),并且ERANGE存储在errno中。如果正确的值会导致下溢,则返回零,并将ERANGE存储在errno中 因此,在我看来,errno应该是零(无错误),或者d应该是零
errno = 0;
d = strtod("1.8011670033376514e-308", NULL);
使用此代码,我得到d==1.8011670033376514e-308
和errno==ERANGE
来自斯特罗德(3):
如果正确的值会导致溢出,则返回加号或减号巨值(巨值,巨值)(根据值的符号),并且ERANGE
存储在errno
中。如果正确的值会导致下溢,则返回零,并将ERANGE
存储在errno
中
因此,在我看来,errno
应该是零(无错误),或者d
应该是零(下溢)
这是一个错误,还是我遗漏了什么?许多不同版本的eglibc和gcc都会出现这种情况。如果strtod()
返回一个非零值(即不是+/-巨大值),则调用已成功(根据您引用的手册页)
请参阅手册页以了解:
头文件定义整数变量errno
,该变量
在发生错误时,由系统调用和某些库函数设置
错误以指示出错的地方。它的价值只有一个
当调用的返回值指示错误时(即,-1
)
大多数系统调用;-1
或NULL
来自大多数库函数)a
允许成功的函数更改errno
因此,如果函数的返回值实际返回一个指示发生错误的值,则只能检查errno
关于errno
(以及它与strtod()
)的关系的更完整的解释可以找到。在§7.22.1.3的strtod()
,strtof()
和strtold()
函数中,C11标准(ISO/IEC 9899:2011)规定:
函数返回转换后的值(如果有)。如果无法执行转换,
返回零。如果正确值溢出且默认舍入生效(7.12.1),
返回正负巨值
,巨值
,或巨值
(根据
返回值的类型和符号),宏ERANGE
的值存储在
errno
。如果结果下溢(7.12.1),函数返回一个数值,其大小为
不大于返回类型中的最小规范化正数;是否
errno
获取实现定义的值erage
本标准还在§5.2.4.2.2浮动类型的特征中指出,IEC 60559(IEEE 754)浮点数具有以下限制:
由于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;
}
具有讽刺意味的是,错误消息是错误的-值太小-但您不可能拥有所有信息。代码的运行方式如下:
如果正确的值会导致下溢,则应返回其大小不大于返回类型中最小标准化正数的值,并将errno设置为[ERANGE]
我想说,您在Linux手册页中看到的是一个详细的错误
#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