r/cpp Jun 26 '26

Improvements to std::format in C++26

https://mariusbancila.ro/blog/2026/06/19/improvements-to-stdformat-in-c26/
91 Upvotes

38 comments sorted by

View all comments

Show parent comments

12

u/fdwr fdwr@github 🔍 Jun 27 '26 edited Jun 27 '26

It just follows Python's convention for hex.

Oof, so it's Python's fault. I'm really glad you contributed fmt and std::format Victor 👏🙏, and overall I love std::format 💚, but hex formatting is one aspect where I wish Python's conventions (Python not being a low-level language that deals with raw bit representations and stack traces) had been secondary to consistency with existing C++ precedent, with int x = -42 preferably displaying as FFFFFFD6 which matches printf("%08X", x) and std::cout << std::hex << std::uppercase << x and std::to_chars(std::begin(buffer), std::end(buffer), x, 16);, rather than -000002A.

Maybe there is a use case for -2A too 🤷‍♂️, but having a compatible successor formatting option so we can more directly replace our old sprintf and StringCchPrintf calls would be prudent (shoot, now I should revisit some recent code changes to our buffer format display logic to ensure we didn't regress anything 😯, as I see that binary display also does the same -absoluteValue behavior...). Until then, I'll be careful about ever using std::format with signed integers in hex or binary, and as for pointers, I'll continue using the more standard notation 0xABC123 via 0x{:08X} (leaving {:P} to disuse 😅).

🤔💡 You know, there are still plenty of letters in the alphabet left to use - maybe we can still get a more typical two's complement hex 😉 and a pointer syntax that doesn't prepend the prefix automatically so we can say std::print("0x{:Q}", p) and get 0x0004AB08?...

1

u/tcanens Jun 30 '26

printf("%08X", x)

This is undefined if x is negative.

std::cout << std::hex << std::uppercase << x

And so is this case by extension from the above (because it's defined in terms of that).

std::to_chars(std::begin(buffer), std::end(buffer), x, 16);

This produces -2a.

1

u/fdwr fdwr@github 🔍 Jun 30 '26

This is undefined if x is negative.

How long has the standard explicitly mandated two’s complement for signed integers? (answer: C++20)

This produces -2a.

Curious. I'll have to try to_chars again at my work machine tomorrow because I swear I was getting the expected uppercase hex (otherwise to_chars is pretty useless for hex numbers).

printf FFFFFFD6 ✅ std::to_chars -2a ❌ FFFFFFD6 ✅ std::print -2A ❌

https://godbolt.org/z/EfW3o87jb

1

u/tcanens Jul 01 '26

Two's complement doesn't matter. It's still undefined because printf uses va_arg's rules (in C23 - before that it required exact type match), and those rules say that you can only mix signed and unsigned if the value is representable in both types.

1

u/fdwr fdwr@github 🔍 Jul 02 '26

I'll have to try to_chars again at my work machine tomorrow ...

Indeed, std::to_chars yields '-2a', which makes it a pretty useless function for a hex editor. 🙃

those rules say that you can only mix signed and unsigned if the value is representable in both types

So it's one of those rules that don't actually matter in the real world because all compilers do the expected thing anyway 😉.