4

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

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • http://ideone.com/sCh4tn why ideone couldn't give the correct number... – Jason Hu Mar 13 '15 at 19:35
  • @HuStmpHrrr: There's a missing header: http://ideone.com/IIBYu0 We're not able to pass `-Wall` to ideone, but if we did, we'd see two warnings for implicit declarations of functions. – Bill Lynch Mar 13 '15 at 19:37
  • @BillLynch i directly copied OP's code. would that be a reason for op doesn't have a proper output? – Jason Hu Mar 13 '15 at 19:54
  • @HuStmpHrrr: chux missed a header. `strtod()` is defined in `stdlib.h`. What's likely occuring is that cygwin's C library includes `stdlib.h` implicitly from the headers in the code. But glibc (which ideone uses) doesn't. So to get the code to not be undefined behavior, we should include that header. – Bill Lynch Mar 13 '15 at 20:04
  • @BillLynch Thanks for the idea. My true code did include `#include ` and I do see I missed that in the cut/paste here. Sorry for the false lead. I will update my post. – chux - Reinstate Monica Mar 13 '15 at 20:08

2 Answers2

4

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.

Community
  • 1
  • 1
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
3

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.

Daniel Kleinstein
  • 5,262
  • 1
  • 22
  • 39