【问题标题】:Unexpected endptr with strtod()/strtold()strtod()/strtold() 出现意外的 endptr
【发布时间】:2015-05-16 10:03:06
【问题描述】:

我希望endptr 指向与strtod()strtold() 相同的值。然而它们不同。我怀疑strtold() 不正确。 OTOH,这可能是规格不明确且任一结果都可接受的情况。

这是一个错误(以及使用哪个函数)还是未定义/未指定的行为?

使用:gcc\x86_64-pc-cygwin\4.8.3

#include <math.h>
#include <stdio.h>

// Edit - This include is in my true code, but was missing in original post
#include <stdlib.h>

int main(void) {
    char *s = "123ez";
    char *endptr;
    double d = strtod(s, &endptr);
    printf("     double %f '%s'\n", d, endptr);
    long double ld = strtold(s, &endptr);
    printf("long double %Lf '%s'\n", ld, endptr);
    return 0;
    }

Output:
     double 123.000000 'ez'
long double 123.000000 'z'

[编辑]

gcc 命令gcc -I"C:\cygwin64\lib\gcc\x86_64-pc-cygwin\4.8.3\include" -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -MMD -MP -MF"string_fp.d" -MT"string_fp.d" -o "string_fp.o" "../string_fp.c"

GCC 4.9.2

【问题讨论】:

  • ideone.com/sCh4tn 为什么 ideone 不能给出正确的数字...
  • @HuStmpHrrr:缺少标题:ideone.com/IIBYu0 我们无法将-Wall 传递给 ideone,但如果这样做,我们会看到两个关于函数隐式声明的警告。
  • @BillLynch 我直接复制了 OP 的代码。这会是 op 没有正确输出的原因吗?
  • @HuStmpHrrr:chux 错过了一个标题。 strtod()stdlib.h 中定义。可能发生的情况是 cygwin 的 C 库从代码的标题中隐式包含 stdlib.h。但是 glibc(ideone 使用)没有。因此,为了使代码不是未定义的行为,我们应该包含该标头。
  • @BillLynch 感谢您的想法。我的真实代码确实包括#include &lt;stdlib.h&gt;,我确实看到我在这里的剪切/粘贴中错过了它。对不起,错误的线索。我会更新我的帖子。

标签: c gcc strtod


【解决方案1】:

两者都不应该使用e。要被允许使用ee 之后必须有一个非空的数字序列。带有 Glibc 2.12 的 GCC 4.9.0 运行正常。

[2:29pm][wlynch@apple /tmp] ./a.out 
     double 123.000000 'ez'
long double 123.000000 'ez'

引用 C 2011 标准草案 N1570 中的内容...

第 7.22.1.3 节第 3 段:strtod、strtof 和 strtold 函数

主题序列的预期形式是可选的加号或减号,然后是以下之一:

  • 一个非空的十进制数字序列,可选地包含一个小数点字符,然后是 6.4.4.2 中定义的可选指数部分;
  • ...

第 6.4.4.2 节浮动常量

exponent-part:
    e signopt digit-sequence
    E signopt digit-sequence
digit-sequence:
    digit
    digit-sequence digit

我认为这是您正在运行的 C 标准库中的一个错误。

【讨论】:

    【解决方案2】:

    这是strtold 的一个错误 - 标准将常量的指数部分的语法定义为 (6.4.4.2):

    exponent-part:
        e sign(optional) digit-sequence
        E sign(optional) digit-sequence
    

    地点:

    digit-sequence:
        digit
        digit-sequence digit
    

    并且digit 被定义为不能为零长度。所以e后面的数字部分不能是零长度。

    strtold 的行为已定义(强调我的):

    strtod、strtof 和 strtold 函数转换初始部分 nptr 指向的字符串的 double、float 和 long double 表示,分别。首先,他们分解输入字符串 分为三个部分:一个初始的,可能是空的,空白序列 字符(由isspace 函数指定),主题序列 类似于浮点常数或表示无穷大或 南;和一个或多个无法识别的字符的最终字符串,包括终止的 null 输入字符串的字符。然后,他们尝试将主题序列转换为 浮点数,并返回结果。

    并定义了主题序列:

    一个非空的十进制数字序列,可选地包含一个 小数点字符,然后是定义的可选指数部分 6.4.4.2.

    由于您的示例中e 之后的数字部分长度为零,因此它不是有效的指数部分。

    【讨论】:

      猜你喜欢
      • 2018-10-31
      • 2011-04-21
      • 2011-10-18
      • 1970-01-01
      • 2017-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多