diff --git a/include/nlohmann/detail/conversions/to_chars.hpp b/include/nlohmann/detail/conversions/to_chars.hpp index 9f8aa8581..93c27c162 100644 --- a/include/nlohmann/detail/conversions/to_chars.hpp +++ b/include/nlohmann/detail/conversions/to_chars.hpp @@ -983,7 +983,8 @@ inline void shortest_digits(char* buf, int& len, int& decimal_exponent, double v std::size_t n = digits.size(); while (d.significand >= 100) { - const auto i = static_cast(d.significand % 100) * 2; + const std::uint64_t two_digits = d.significand % 100; // a variable: GCC calls a cast of the remainder useless where std::uint64_t is std::size_t + const auto i = static_cast(two_digits) * 2; d.significand /= 100; n -= 2; digits[n] = pairs[i]; diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 373abc66e..401f67ebe 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -25114,7 +25114,8 @@ inline void shortest_digits(char* buf, int& len, int& decimal_exponent, double v std::size_t n = digits.size(); while (d.significand >= 100) { - const auto i = static_cast(d.significand % 100) * 2; + const std::uint64_t two_digits = d.significand % 100; // a variable: GCC calls a cast of the remainder useless where std::uint64_t is std::size_t + const auto i = static_cast(two_digits) * 2; d.significand /= 100; n -= 2; digits[n] = pairs[i]; diff --git a/tests/src/unit-to_chars.cpp b/tests/src/unit-to_chars.cpp index 6cc8ae6da..02895cc9d 100644 --- a/tests/src/unit-to_chars.cpp +++ b/tests/src/unit-to_chars.cpp @@ -20,8 +20,11 @@ using nlohmann::detail::dtoa_impl::reinterpret_bits; #include #include #include +#include #include +#include #include +#include #include #include #include @@ -664,9 +667,11 @@ void check_shortest(double v) if (digits.size() > 1) { // the decimals of one digit fewer next to the value - std::array shorter{}; - const int n = std::snprintf(shorter.data(), shorter.size(), "%.*e", static_cast(digits.size()) - 2, v); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - const auto near = digits_and_exponent(std::string(shorter.data(), static_cast(n))); + // (a stream rather than snprintf("%.*e"), whose output GCC cannot bound) + std::ostringstream shorter; + shorter.imbue(std::locale::classic()); + shorter << std::scientific << std::setprecision(static_cast(digits.size()) - 2) << v; + const auto near = digits_and_exponent(shorter.str()); // as an integer with digits.size() - 1 digits std::string m = near.first; int e = near.second;