Неожиданный endptr с strtod()/strtold()

Я бы ожидал 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

2 ответа

Решение

Ни один не должен потреблять e, Должно быть разрешено потреблять eдолжна быть непустая последовательность цифр после e, И GCC 4.9.0 с Glibc 2.12 ведет себя корректно.

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

Цитируя вещи из проекта N1570 стандарта C 2011...

Раздел 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, с которой вы работаете.

Это ошибка с 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 function) - предметная последовательность, напоминающая константу с плавающей точкой или представляющая бесконечность или NaN; и окончательная строка из одного или нескольких нераспознанных символов, включая завершающий нулевой символ входной строки. Затем они пытаются преобразовать последовательность объекта в число с плавающей запятой и вернуть результат.

И предметная последовательность определяется:

непустая последовательность десятичных цифр, необязательно содержащая символ десятичной точки, а затем необязательная часть экспоненты, как определено в 6.4.4.2.

И так как числовая часть после e в вашем примере это нулевая длина, это не допустимая экспонентная часть.

Другие вопросы по тегам