В стандартном C нет переносимого способа обнаружить ошибки преобразования строки в число с плавающей запятой

No portable way to detect string-to-float conversion errors in standard C

Автор разбирает, почему в стандартном C невозможно надёжно проверить ошибки преобразования строки в число с плавающей запятой. Функции strtod и подобные зависят от math_errhandling: если поддержка errno не заявлена, ошибки переполнения и антипереполнения могут не устанавливать errno. POSIX требует всегда устанавливать errno, что противоречит стандарту C. На практике glibc и musl ведут себя по-разному при неверном вводе, а man-страницы умалчивают об этом.

на glibc это печатает 0, потому что strtod в glibc никогда не устанавливает errno в EINVAL. musl, напротив, устанавливает errno в EINVAL, так что печатается «22».
  1. Joker_vD

    Поразительно, как историческая неспособность широко используемых языков программирования (от FORTRAN вплоть до, скажем, Java/C#) эргономично возвращать два значения из вызова функции заставила людей изобретать всевозможные безумные API/контракты.

    [double x, errno_t errno] = strtod(s, nullptr);

    if (errno != 0) {

    // ...

    }

    [x, _] = strtod(s, nullptr); // Когда вы уверены, что ошибка невозможна, или вам просто плевать

    Вместо этого мы имеем в лучшем случае «проверьте, не равно ли возвращаемое значение -1, и если да, проверьте глобальную переменную errno», а в худшем — «функция на самом деле не сообщает надёжно о своих ошибках, так что не подсовывайте ей некорректные данные, мне всё равно».

  2. Panzerschrek

    Функции разбора чисел в C принципиально сломаны, поскольку зависят от локали. Есть куча багов, когда кто-то разбирает число, предполагая, что в нём десятичная точка, но потом на системах с локалью, отличной от той, что была на машине разработчика, внезапно оказывается запятая вместо точки. Так что их почти всегда следует избегать и использовать std::from_chars (доступна в новых версиях C++) или какую-нибудь другую стороннюю библиотеку.

  3. gucci-on-fleek

    > в man-страницах Linux для этих функций об этом вообще ничего не сказано

    > тот факт, что в man-странице никогда не отмечается, что это расширение ([…]), для меня действительно примечателен.

    > это совершенно не задокументировано на man-странице Linux.

    Сопровождающие man-страниц Linux, по моему опыту, очень дружелюбны, так что, вероятно, стоит сообщить им об этом [0] [1].

    [0]: https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/...

    [1]: https://lore.kernel.org/linux-man/

  4. kazinator

    Не забывайте про локаль! Если вы находитесь в неправильной локали, strtod("3,4", ...) может вернуть 3.4 и т.д.

  5. chasil

    IEEE-754 — суровая госпожа.

    https://en.wikipedia.org/wiki/IEEE_754

Ещё за этот день

2026-10-12