Hi, using sprintf to format a long long value narrows it to plain long if %ld is used. All other methods (%lld, %d and of course format) format as long long.
Sure, using %ld with long long is UB and C sprintf also narrows, but fmt has full type information and could do better, as it already does with %d.
Some examples below
fmt::sprintf("%llu", ULLONG_MAX) -> 18446744073709551615
fmt::sprintf("%lu", ULLONG_MAX) -> 4294967295
fmt::sprintf("%u", ULLONG_MAX) -> 18446744073709551615
fmt::format("{}", ULLONG_MAX) -> 18446744073709551615
fmt::sprintf("%lld", LLONG_MIN) -> -9223372036854775808
fmt::sprintf("%ld", LLONG_MIN) -> 0
fmt::sprintf("%d", LLONG_MIN) -> -9223372036854775808
fmt::format("{}", LLONG_MIN) -> -9223372036854775808
fmt::sprintf("%lld", LLONG_MAX) -> 9223372036854775807
fmt::sprintf("%ld", LLONG_MAX) -> -1
fmt::sprintf("%d", LLONG_MAX) -> 9223372036854775807
fmt::format("{}", LLONG_MAX) -> 9223372036854775807
Cannot repro: https://godbolt.org/z/jnKKnr.
perhaps is something MSVC specific. I'll check.
Thanks
It's platform specific. On windows long is 32bit and long long 64, while on linux both are 64bit, so a cast doesn't change values.
In printf.h line 547 there is
case 'l':
if (t == 'l') {
++it;
t = it != end ? *it : 0;
convert_arg<long long>(arg, t);
} else {
convert_arg<long>(arg, t);
}
break;
On linux the convert_arg<long>(arg, t); is a no-op between long and long long, while on windows it truncates to 32bit
The conversion is intentional for consistency with printf: https://godbolt.org/z/5oq713. If you want to avoid it, use fmt::print.
well, yes, but fmt knows the parameter real type and could do better than printf, like it does for plain %u: https://godbolt.org/z/Wbhb69
Imho this is one of great features of fmt: the ability of furnish a printf like interface but avoiding a whole class of C-related problems and errors
Obviously the format interface is way better (BTW, thanks for making it a standard!), but for legacy code fmt::sprintf is wonderful.
PS sorry, I've used the wrong account for commenting
Here, compatibility with printf is more important. fmt::printf is only there for migrating legacy code.
ok, I understand, thanks.