Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unknown conversion type character 'b' in format #135

Closed
KarlK90 opened this issue Jun 29, 2022 · 12 comments
Closed

Unknown conversion type character 'b' in format #135

KarlK90 opened this issue Jun 29, 2022 · 12 comments

Comments

@KarlK90
Copy link

KarlK90 commented Jun 29, 2022

TLDR: b will be an offical format specifier with the upcoming C2X C standard, until then this warning can only be suppressed or some workaround applied as motioned in this thread.

Hi @eyalroz,

I've encountered this format warning with arm-none-eabi-gcc version 10.3.1 on a Ubuntu 22.04 host using the latest develop branch of printf. I'm trying to print a regular byte value in its binary representation using this macro, note that xprintf is just a redefine for printf.

#define print_bin_reverse8(i) xprintf("%08b", bitrev(i))

My question is now, can this warning be prevented with a different format attribute that covers this non-standard format specifier?

The whole error log is (this in in qmk_firmware if you are curious):

quantum/matrix_common.c: In function 'matrix_print':
quantum/logging/print.h:85:39: error: unknown conversion type character 'b' in format [-Werror=format=]
   85 | #define print_bin_reverse8(i) xprintf("%08b", bitrev(i))
      |                                       ^~~~~~
quantum/matrix_common.c:74:35: note: in expansion of macro 'print_bin_reverse8'
   74 | #    define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
      |                                   ^~~~~~~~~~~~~~~~~~
quantum/matrix_common.c:89:9: note: in expansion of macro 'print_matrix_row'
   89 |         print_matrix_row(row);
      |         ^~~~~~~~~~~~~~~~
quantum/logging/print.h:85:43: note: format string is defined here
   85 | #define print_bin_reverse8(i) xprintf("%08b", bitrev(i))
      |                                           ^
quantum/logging/print.h:85:39: error: too many arguments for format [-Werror=format-extra-args]
   85 | #define print_bin_reverse8(i) xprintf("%08b", bitrev(i))
      |                                       ^~~~~~
quantum/matrix_common.c:74:35: note: in expansion of macro 'print_bin_reverse8'
   74 | #    define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
      |                                   ^~~~~~~~~~~~~~~~~~
quantum/matrix_common.c:89:9: note: in expansion of macro 'print_matrix_row'
   89 |         print_matrix_row(row);
      |         ^~~~~~~~~~~~~~~~
@eyalroz
Copy link
Owner

eyalroz commented Jun 29, 2022

Let's start with:

  1. Showing me this warning on a proper, non-macro, command.
  2. Putting that command in an actual program.
  3. Specifying the command-line you used which resulted in this error message.

@eyalroz
Copy link
Owner

eyalroz commented Jun 29, 2022

But I will say that %b is not in the C standard, IIANM. So, if you do strict format checking - you are going to get a warning about that.

@KarlK90
Copy link
Author

KarlK90 commented Jun 29, 2022

As a minimal, macro free example a main.c in the root directory of printf

#include "printf/printf.h"

void putchar_(char character) {
    (void)(character);
}

// Only for arm-none-eabi-gcc
void _exit(int status) {
    (void)(status);
    while (1) {
    }
}

int main(void) {
    printf_("%08b", 0xFF);
    return 0;
}

and compiled with regular x84_64 GCC version 11.2.0 will result in the following warnings:

❯ gcc -I ./src src/printf/printf.c main.c
main.c: In function ‘main’:
main.c:14:17: warning: unknown conversion type character ‘b’ in format [-Wformat=]
   14 |     printf_("%08b", 0xFF);
      |                 ^
main.c:14:13: warning: too many arguments for format [-Wformat-extra-args]
   14 |     printf_("%08b", 0xFF);
      |  

arm-none-eabi-gcc version 10.3.1 will only flag it with the -Wall flag though.

But I will say that %b is not in the C standard, IIANM. So, if you do strict format checking - you are going to get a warning about that.

Hmmn, this is unfortunate. I skimmed to format attribute pages of GCC but didn't find an alternative format specifier that would maybe cover it. This is was also the main reason why I opened this issue in the hope that there might be a undocumented workaround without disabling these checks.

@eyalroz
Copy link
Owner

eyalroz commented Jun 29, 2022

@KarlK90 : We can't "hold stick from both ends" - either we use only standard specifiers, or we don't require using standard specifiers...

However - you could write a macro which suppresses the warning/error, I think. Have a look at tests/test_suite.cpp, and specifically, DISABLE_WARNING_PRINTF_FORMAT_INVALID_SPECIFIER and its use.

@KarlK90
Copy link
Author

KarlK90 commented Jun 29, 2022

Alright, the selective suppression of warnings solution was the one I would have liked to avoid. But that seems to be the only solution if I want to retain format warnings for all other cases.

@KarlK90 KarlK90 closed this as completed Jun 29, 2022
@mickjc750
Copy link

@KarlK90, You could always re-purpose the existing %o specifier in your own fork or implementation to output binary. Although if you deviate from standard behaviour, I'd recommend at least one compilation warning to alert future readers of your code. I've done this for both %o and %n, as the standard behaviour of these wasn't useful to me.

@eyalroz
Copy link
Owner

eyalroz commented Jun 30, 2022

@mickjc750 : Well, that is possible, but - unless Karl is the only user of the modified version, I would recommend against this, since changing the semantics of specifiers would be confusing for other developers.

@KarlK90
Copy link
Author

KarlK90 commented Jun 30, 2022

Yes this is unfortunately not really an option, the QMK user base is large with about 3000 keyboards (+users) only in the main repo. But that solution would work for me as single person.

@KarlK90
Copy link
Author

KarlK90 commented Jul 1, 2022

I did a bit of digging where these format arguments are actually implemented and low and behold b will be valid format specifier in the upcoming C2X C standard 🎉 It is already included in the GCC sources as you can see here -> https://github.com/gcc-mirror/gcc/blob/master/gcc/c-family/c-format.cc#L709 but it will definitely be a while until this C standard and compiler versions will trickle down into our stack... In the meantime I'll just selectively disable the warnings.

@mickjc750
Copy link

@KarlK90 Thanks, that's good news :-) I did have one other idea. Depending on how many bits you need, you may be able to wrap your argument with a function that does some bit shifting, so that a %llo shows the same digits. You get 22 digits with %llo.

@KarlK90
Copy link
Author

KarlK90 commented Jul 1, 2022

Thanks, that is a neat trick for sure! Unfortunately we have binary output helpers up to 32 digits long... so that won't be applicable here here.

@eyalroz
Copy link
Owner

eyalroz commented Jul 1, 2022

@KarlK90 Oh, yes, I know that. But it'll be years before this propagates to all platforms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants