From ed97d9a3a201cda4f99fb19c7fce5df9209a5d72 Mon Sep 17 00:00:00 2001 From: fhgffy <102001626+fhgffy@users.noreply.github.com> Date: Thu, 8 Oct 2026 23:56:57 +0800 Subject: [PATCH] Ignore '+' and space flags for unsigned printf conversions C only applies the '+' and space flags to signed conversions, so fmt::sprintf("%+u", 42) should give "42" like printf does, not "+42". The same goes for %o, %x and %X. --- include/fmt/printf.h | 3 +++ test/printf-test.cc | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/fmt/printf.h b/include/fmt/printf.h index e25e6fba..03c8746d 100644 --- a/include/fmt/printf.h +++ b/include/fmt/printf.h @@ -545,6 +545,9 @@ void vprintf(buffer& buf, basic_string_view format, if (it == end) report_error("invalid format string"); char type = static_cast(*it++); if (is_integral_type(arg.type())) { + // The '+' and space flags only apply to signed conversions. + if (type == 'u' || type == 'o' || type == 'x' || type == 'X') + specs.set_sign(sign::none); // Normalize type. switch (type) { case 'i': diff --git a/test/printf-test.cc b/test/printf-test.cc index f8322522..e2a06f8d 100644 --- a/test/printf-test.cc +++ b/test/printf-test.cc @@ -169,6 +169,14 @@ TEST(printf_test, plus_flag) { // '+' flag and space flag are both ignored for non-numeric types. EXPECT_PRINTF("x", "%+ c", 'x'); EXPECT_PRINTF("x", "% +c", 'x'); + + // '+' flag is ignored for unsigned conversions. + EXPECT_PRINTF("42", "%+u", 42); + EXPECT_PRINTF("42", "%+o", 042); + EXPECT_PRINTF("2a", "%+x", 0x2a); + EXPECT_PRINTF("2A", "%+X", 0x2a); + EXPECT_PRINTF("0x002a", "%+#06x", 0x2a); + EXPECT_PRINTF("", "%+.0u", 0); } TEST(printf_test, minus_flag) { @@ -199,6 +207,12 @@ TEST(printf_test, space_flag) { // ' ' flag is ignored for non-numeric types. EXPECT_PRINTF("x", "% c", 'x'); + + // ' ' flag is ignored for unsigned conversions. + EXPECT_PRINTF("42", "% u", 42); + EXPECT_PRINTF("42", "% o", 042); + EXPECT_PRINTF("0002a", "% 05x", 0x2a); + EXPECT_PRINTF("2A", "% X", 0x2a); } TEST(printf_test, hash_flag) {