chux
chux

Reputation: 153582

Unexpected endptr with strtod()/strtold()

I'd expect the endptr to point to the same value with both strtod() and strtold(). Yet they differ. I suspect strtold() is incorrect. OTOH, this could be a case where the spec is not clear and either result is acceptable.

Is this a bug (and with which function) or undefined/unspecified behavior?

Using: 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'

[Edit]

gcc comand 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

Upvotes: 4

Views: 420

Answers (2)

Daniel Kleinstein
Daniel Kleinstein

Reputation: 5502

It's a bug with strtold - the standard defines the syntax of an exponent part of a constant as (6.4.4.2):

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

Where:

digit-sequence:
    digit
    digit-sequence digit

And digit is defined so that it can't be zero-length. So the numeric part after the e can't be zero-length.

The behavior of strtold is defined (emphasis mine):

The strtod, strtof, and strtold functions convert the initial portion of the string pointed to by nptr to double, float, and long double representation, respectively. First, they decompose the input string into three parts: an initial, possibly empty, sequence of white-space characters (as specified by the isspace function), a subject sequence resembling a floating-point constant or representing an infinity or NaN; and a final string of one or more unrecognized characters, including the terminating null character of the input string. Then, they attempt to convert the subject sequence to a floating-point number, and return the result.

And the subject sequence is defined:

a nonempty sequence of decimal digits optionally containing a decimal-point character, then an optional exponent part as defined in 6.4.4.2.

And since the numeric part after the e in your example is zero-length, it isn't a valid exponent part.

Upvotes: 3

Bill Lynch
Bill Lynch

Reputation: 81936

Neither should consume the e. To be allowed to consume the e, there must be a non-empty sequence of digits after the e. And GCC 4.9.0 with Glibc 2.12 behaves correctly.

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

Citing things from draft N1570 of the C 2011 standard...

Section 7.22.1.3 Paragraph 3: The strtod, strtof, and strtold functions

The expected form of the subject sequence is an optional plus or minus sign, then one of the following:

  • a nonempty sequence of decimal digits optionally containing a decimal-point character, then an optional exponent part as defined in 6.4.4.2;
  • ...

Section 6.4.4.2 Floating Constants

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

I would consider this a bug in the C standard library that you are running against.

Upvotes: 4

Related Questions