MinGW-GCC: "Unbekanntes Konvertierungstyp-Zeichen 'h'" (snprintf)
Okay, ich habe ein seltsames Problem kompilieren eine C-Datei mit MinGW (GCC 4.6.2) auf Windows 7. Die fragliche Datei enthält die folgenden C-code:
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("%2hhX\n", 250);
char c[80];
snprintf(c, sizeof(c), "%2hhX", 250);
printf("%s\n", c);
return 0;
}
Die Zusammenstellung zeigt sich, wie diese:
$ 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]
Nun, was bei mir seltsam ist, dass es Beschwerden über die snprintf
- Aufruf in Zeile 6, aber nicht die printf
Anruf auf der Linie 4. Bin ich etwas fehlt, oder warn das nur falsch? Auch, gibt es vielleicht eine bessere Entsprechung für den format-string "%2hhX"
? (Ich bin versucht zu drucken char-Variablen als hexadezimal-Werte.)
- Interessanterweise funktioniert es mit GCC 4.3.4: ideone.com/LAPP9. Ich habe auch versucht mit 4.1.2, und es ist in Ordnung auf diese zu.
- Mit MinGW-GCC-4.6.1 bekomme ich Warnungen auf beiden
printf()
und diesnprintf()
- was MinGW-Distribution verwenden Sie? Ich bin derzeit mit der TDM-Verteilung. - Uh, ich war gar nicht bewusst, dass es mehrere MinGW-Distributionen. Ich bin mit dem "standard" ein, ich denke (mingw.org, installiert mit sourceforge.net/projects/mingw/files/Installer/mingw-get-inst). Würde das einen Unterschied machen, obwohl?
- Außerdem bin ich noch mehr verwirrt, jetzt haben wir 3 verschiedene Verhaltensweisen auf 4 Versionen von GCC. Der format-string ist gültig, obwohl, ist es nicht?
- Ich verwende in der Regel TDM ist MinGW (tdm-gcc.tdragon.net) und/oder nuwen s (nuwen.net/mingw.html). Ich habe festgestellt, dass Sie viel einfacher zu installieren als die offizielle MinGW (nuwen ist buchstäblich Auspacken eines Archivs), Sie-Paket weitere nützliche Bibliotheken (z.B. pthreads-win32-in TDM-und Boost in nuwen) und TDM hat eine option für ein 64-bit-targeting-compiler.
- alles was ich sicher weiß ist, dass 4.6.1 ist
snprintf()
scheint nicht zu behandeln"%2hhX"
wie ich erwarte - es ignoriert die zusätzlichenh
also, wenn Sie eine negative Zahl oder ein unsigned mit einem größeren Wert als 255 bekommen Sie mehr als zwei Zeichen ausgedruckt. Ich denke, dass technisch das ist Undefiniertes Verhalten, aber immer noch, wenn Sie erwarten sind nur die niederwertigsten byte gedruckt werden, einige weitere test könnte in Ordnung sein. 4.7.0 funktioniert wie erwartet, habe ich nicht einen 4.6.2 testen. - Für mich funktioniert es so wie erwartet (4.6.2); unabhängig davon, ob ich den pass in negative oder große Werte, erhalte ich nur zwei Zeichen, der/das am wenigsten signifikante byte.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Historisch, MinGW wurde in eine etwas seltsame situation, insbesondere soweit die C99-Unterstützung geht. MinGW stützt sich hauptsächlich auf die msvcrt.dll Laufzeit verteilt mit Windows, und dass die Laufzeit nicht unterstützt C99.
Also mit älteren Versionen von MinGW, können Sie in Probleme ausgeführt, im C99-Modus wenn Sie mit dem C99-spezifische format-Bezeichner. Auch historisch gesehen, GCC hat keine spezielle Unterkünfte für msvcrt.dll's fehlende Unterstützung für C99-Definitionen. So dass Sie bekommen würde, in Situationen, in denen
-Wformat
würde nicht warnen, dass ein format, dass würde nicht funktionieren.Dinge verbessern, auf beiden Seiten - GCC hat, die konkrete Unterstützung für -Wformat beim Einsatz mit dem MS-Laufzeitumgebung, wie:
-Wpedantic-ms-format
so, dass GCC nicht beschweren"I32"
und"I64"
(obwohl es ist dokumentiert, ich bekomme immer noch eine Beschwerde darüber, dass es unbekannte sogar in 4.7.0 - vielleicht ist es neu)ms_printf
option__attribute__((__format__))
Auf der anderen Seite, MinGW hat seine eigenen
snprintf()
für eine Weile, da MSVC-Variante,_snprintf()
verhält sich ganz anders. Allerdings MinGW verlassen für eine lange Zeit auf derprintf()
im msvcrt.dll so C99 Formatbezeichner fürprintf()
hat nicht funktioniert. Irgendwann MinGW damit begonnen, eine eigene versionprintf()
und Freunde, so dass Sie könnte die richtige C99 (und GNU?) Unterstützung. Es scheint jedoch, dass auf der konservativen Seite, diese nicht ersetzen msvcrt.dll Versionen zunächst. Sie haben Namen wie__mingw_printf()
.Sieht es aus wie an einem gewissen Punkt zwischen 4.6.1 und 4.7.0, das MinGW-Header begann mit dem mitgelieferten MinGW-Versionen, die als Ersatz für die msvcrt.dll Funktion (zumindest wenn Sie schon angegeben C99).
Allerdings scheint es, dass mit den neueren Versionen von GCC und MinGW noch ein wenig out-of-sync. Wo, wie vor dem GCC würde nicht warnen, Planern, die nicht wirklich arbeiten auf MinGW, das nicht beschwert es sich über spcifiers wird.
Möchten Sie vielleicht versuchen Sie, die folgenden snipet von code, um zu sehen, wie gut Ihre version von MinGW unterstützen
"hhX"
:Ich bin mir nicht sicher, was Sie vorschlagen, um das problem zu beheben, Sie sind in Betrieb - ich denke, dass Sie möglicherweise in der Lage, um den patch MinGW
stdio.h
- header, so dass es eine__attribute__((__format__ (gnu_printf, ...)))
- Attribut auf die printf-Funktionen (gibt es nicht in den neuerenstdio.h
, so wird GCC verwenden Sie die Standard-Vorstellung von dem, was das format unterstützt wird).44
zweimal, wie man erwarten würde; es scheint, dass nursnprintf
ist insbesondere betroffen von der Warnung auf meine installation. Doch, der code, den ich oben gepostet DruckeFA
zweimal, so dass die Funktion scheint zu funktionieren korrekt. So, im wesentlichen, die Warnung ist in der Tat falsch und es ist nur eine Laune, die mit MinGW und GCC? Wenn dem so ist, dass alles, was ich wirklich wissen müssen - ich wollte nur herausfinden, ob ich etwas übersehen im code, oder wenn ich könnte, ignorieren Sie die Warnung.__mingw_printf
ist die eine, die funktioniert bei mir ohne Warnungen. Werden wickeln Sie es in ein makro für die Allgemeinheit.Zusätzlich zu den anderen Antworten, hier ist einige weitere Infos über printf-format-Prüfungen im GCC:
Wenn Sie sagen
__attribute__((__format__ (FORMAT, ...)))
, den Wert vonFORMAT
werden kann (so weit wie printf betroffen ist) eine der folgenden Optionen:printf
,gnu_printf
,ms_printf
.ms_printf
macht GCC davon aus, dass die Funktion ein format-string bestimmt für Microsoft Visual Studio CRT-printf-Familie Funktionen. Es bedeutet, dass der GCC wird sich überz
,hh
undll
, aber passI64
ohne Warnung.gnu_printf
macht GCC davon ausgehen GNU libc printf-Implementierung unter (oder vielleicht auch nur ein POSIX/C99-konform printf Umsetzung, ich bin mir nicht sicher). Daher wird GCC beschweren sich überI64
und andere Microsoft-Erweiterungen, aber akzeptierenz
,hh
undll
.printf
ist ein alias fürms_printf
beim kompilieren für Windows, und ein alias fürgnu_printf
sonst.Beachten Sie, dass dieser check ist völlig orthogonal zu den eigentlichen printf-Implementierung verwendet wird. Dies ist leicht zu sehen, wenn Sie schreiben Ihre eigenen printf-like-Funktion und setzen
__attribute__((__format__ (FORMAT, ...)))
auf it - GCC wird sich über verschiedene Dinge, je nachFORMAT
, aber Sie können tun, was immer Sie wollen innerhalb der Funktion.Verfügbar printf-Implementierungen, die ich kenne:
-D__USE_MINGW_ANSI_STDIO=1
) in MinGW.org und MinGW-w64 toolchains. Entsprichtms_printf
(vollständig?) undgnu_printf
- format (teilweise nicht-Unterstützung von positionalen Argumenten).-D__USE_MINGW_ANSI_STDIO=1
). Entsprichtms_printf
(duh...), Einhaltung dergnu_printf
ist sehr gering und hängt von Laufzeit-version (alte Versionen nicht unterstützenll
, neue tun;z
undhh
werden nicht unterstützt in jeder version so weit; GCC ist glücklicherweise nichts von diesen Entwicklungen aber, und übernimmt schlimmsten Fall msvcrt von VC 6.0-ära, es scheint).ms_printf
undgnu_printf
vollständig (oder nahezu vollständig).Den
stdio.h
header in MinGW.org nicht verwendenattribute format
.Den
stdio.h
header in MinGW-w64 verwendetattribute format gnu_printf
für MinGW ANSI STDIO-Implementierung, aber nicht alles verwenden, was für MSVCRT Umsetzung. BEHOBEN: In neueren Versionen von MinGW-w64-Headerstdio.h
verwendenattribute format ms_printf
für MSVCRT Umsetzung.gnulib ist bewusst, der Unterschied zwischen
printf
undgnu_printf
, und wählen Sie eine oder die andere abhängig von einem komplizierten Makros (vermutlich, begleitet mit einer ordnungsgemäßen Umsetzung, die unterstützt, was das format sagt, es tut).Stücke von software, die bekannt sind (im moment) noch Probleme mit GCC-format-Prüfungen:
printf
- format, aber die Umsetzung ist aus gnulib; es gibt eine hervorragende bug, es zu ändern, umgnu_printf
z
Formaten, aber die offiziellen binaries gebaut werden, gegen MSVCRT; es nutzt auchprintf
- format in den Erweiterungs-Header, obwohl Erweiterungen verwenden oftz
sowie