Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
426 views
in Technique[技术] by (71.8m points)

c - MinGW GCC: "Unknown conversion type character 'h'" (snprintf)

Okay, I've run into a strange issue compiling a C file with MinGW (GCC 4.6.2) on Windows 7. The file in question contains the following C code:

#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("%2hhX
", 250);
    char c[80];
    snprintf(c, sizeof(c), "%2hhX", 250);
    printf("%s
", c);
    return 0;
}

The compilation turns out like this:

$ gcc.exe -std=c99 -pedantic -Wall test.c
test.c: In function 'main':
test.c:6:2: warning: unknown conversion type character 'h' in format [-Wformat]
test.c:6:2: warning: too many arguments for format [-Wformat-extra-args]

Now, what's strange to me is that it complains about the snprintf call on line 6, but not the printf call on line 4. Am I missing something or is the warning just incorrect? Also, is there perhaps a better equivalent for the format string "%2hhX"? (I'm trying to print char variables as hexadecimal values.)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Historically, MinGW has been in a bit of an odd situation, especially as far as C99 support goes. MinGW relies mostly on the msvcrt.dll runtime that's distributed with Windows, and that runtime doesn't support C99.

So with older versions of MinGW, you can run into problems in C99 mode when using C99-specific format specifiers. Also historically, GCC didn't make any special accommodations for msvcrt.dll's lack of support for C99 specifiers. So you'd get into situations where -Wformat wouldn't warn about a format that wouldn't work.

Things are improving on both sides - GCC has specific support for -Wformat when used with the MS runtime, such as:

  • -Wpedantic-ms-format so that GCC won't complain about "I32" and "I64" (even though it's documented, I still get a complaint about it being unrecognized even in 4.7.0 - maybe it's brand new)
  • the ms_printf option to __attribute__((__format__))

On the other side, MinGW has provided its own snprintf() for a while, since MSVC's variant, _snprintf(), behaves quite differently. However, MinGW relied for a long while on the printf() in msvcrt.dll, so C99 format specifiers for printf() didn't work. At some point MinGW started providing it's own version of printf() and friends so that you could get proper C99 (and GNU?) support. However, it seems that to be on the conservative side, these didn't replace the msvcrt.dll versions initially. They have names like __mingw_printf().

It looks like at some point between 4.6.1 and 4.7.0, the MinGW headers started using the MinGW supplied versions as replacements for the msvcrt.dll function (at least if you've specifed C99).

However, it seems that with the newer versions, GCC and MinGW are still a little out of sync. Where as before GCC would not warn about specifiers that wouldn't actually work on MinGW, not it complains about spcifiers that will.

You may want to try the following snipet of code to see how well your version of MinGW support "hhX":

printf("%hhX
", 0x11223344);
__mingw_printf("%hhX
", 0x11223344);

I'm not sure what to suggest to fix the problem you're running into - I think that you may be able to patch the MinGW stdio.h header so that it has a __attribute__((__format__ (gnu_printf, ...))) attribute on the printf functions (they're not there in the newer stdio.h, so GCC will use it's default idea of what the format support is).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...