Was ist der Zweck der h-und hh-Modifikatoren für printf?
Abgesehen von %hn
und %hhn
(wo die h
oder hh
gibt die Größe der Spitzen-zu Objekt), was ist der Punkt, der h
und hh
Modifikatoren für printf
Formatbezeichner?
Aufgrund der Standard-promotions, die von der Norm geforderten angewendet werden bei variadischen Funktionen, ist es unmöglich, die Argumente vom Typ char
oder short
(oder jede signed/unsigned-Varianten davon)printf
.
Laut 7.19.6.1(7), die h
modifier:
Gibt an, dass eine nachfolgende d -, i, o, u, x oder X umwandlungsspezifikator gilt für eine
Typ short int oder unsigned short-int-argument (das argument wird
gefördert wurden entsprechend den integer-promotions, aber sein Wert wird
umgewandelt werden zum Typ short int oder unsigned short int vor dem drucken);
oder eine folgende n-Umwandlung Planer gilt ein Zeiger auf ein short
int-argument.
Wenn das argument war eigentlich der Typ short
oder unsigned short
, dann Förderung zu int
gefolgt von einer Umwandlung zurück zu short
oder unsigned short
wird der Ertrag der gleichen Wert als Förderung zu int
ohne Konvertierung zurück. So, für Argumente vom Typ short
oder unsigned short
, %d
, %u
usw. geben sollte identische Ergebnisse zu %hd
, %hu
usw. (und ebenso für char
Arten und hh
).
Soweit ich das beurteilen kann, die einzige situation, in der h
oder hh
modifier könnte möglicherweise nützlich ist, wenn das übergebene argument es eine int
außerhalb der Reichweite von short
oder unsigned short
z.B.
printf("%hu", 0x10000);
aber mein Verständnis ist, dass man die falsche Art, wie diese Ergebnisse zu undefiniertem Verhalten sowieso, so dass Sie konnte es nicht erwarten, es zu drucken 0.
Einer realen Welt Falle, die ich gesehen habe ist der code wie dieser:
char c = 0xf0;
printf("%hhx", c);
denen der Autor erwartet, dass es zu drucken f0
trotz der Umsetzung mit einem einfachen char
Typ, der zu Unterschreiben (in dem Fall printf("%x", c)
drucken würde fffffff0
oder ähnliches). Aber ist diese Erwartung gerechtfertigt?
(Hinweis: Was passiert, ist, dass die ursprüngliche Art war char
, die beworben wird zu int
umgewandelt und zurück unsigned char
statt char
, wodurch sich der Wert, wird gedruckt. Aber nicht den standard angeben, dieses Verhalten, oder ist es ein detail, dass kaputte software könnte sich auf?)
Sehr schöne Frage. Ich arbeite auf eine formatierte i/o-Implementierung, und jetzt, während Sie versuchen, zu verfolgen die standard-stieß ich auf die gleiche Frage. Vielen Dank für die Veröffentlichung
InformationsquelleAutor R.. | 2011-01-03
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ein möglicher Grund: für die Symmetrie mit den Einsatz von Modifikatoren in die formatierte Eingabe-Funktionen? Ich weiß, es wäre nicht unbedingt notwendig, aber möglicherweise war es Wert gesehen?
Obwohl Sie gar nicht erwähnen, die Bedeutung der Symmetrie für das "h" und "hh" Modifikatoren in der C99-Rationale Dokument, der Ausschuss erwähnt, dass es als Gegenleistung dafür, warum das "%p" conversion specifier unterstützt
fscanf()
(obwohl, das war nicht neu für C99 - "%p" Unterstützung ist in C90):Im Abschnitt
fprintf()
, der C99-rationale Dokument nicht diskutieren, dass "hh" Hinzugefügt wurde, sondern lediglich verweist den Leser auf diefscanf()
Abschnitt:Ich weiß, es ist ein dünner Faden, aber ich bin zu spekulieren sowieso, so dass ich dachte, ich würde alles geben, was argument, es könnte sein.
Auch, der Vollständigkeit halber, das "h" - modifier wurde in der original-C89-standard - vermutlich würde es da sein, selbst wenn es nicht unbedingt notwendig, weil der weit verbreiteten bestehenden Gebrauch, auch wenn es vielleicht nicht gewesen, eine technische Voraussetzung, um mit dem Modifikator.
h
undhh
Modifikatoren?Ich bin mir nicht sicher - ich bin nicht sicher, dass dies nicht definiertes Verhalten zur Folge:
printf("%hu", (unsigned int) 0x10000);
. Ich kann mir vorstellen, Argumente in beide Richtungen - ich würde es vorziehen, dass es war gut definiert, aber konnte sehen, dass die Formulierung "Gibt an, dass eine nachfolgende d -, i, o, u, x oder X umwandlungsspezifikator gilt für den Typ short int oder unsigned short-int-argument" wirft diese in die undefinierten Territorium, obwohl die unmittelbar folgende "(das argument wird gefördert wurden entsprechend den integer-promotions, aber der Wert konvertiert werden, um short int oder unsigned short int vor dem drucken)" wirft es zurück.basierend auf diesem text, ich denke, es wäre sinnvoll, für eine Umsetzung zu "konvertieren short int oder unsigned short int" mit optimierten code, der annimmt, dass der Wert, den diese Konvertierung ist in der Tat das Ergebnis der Förderung, wie der standard sagt, es ist. Sagte optimierten code könnte unter Umständen etwas tun, unsinnig, mit einer out-of-range-Wert, so ist es zumindest plausibel geltend machen, durch die Umsetzung, dass es sollte werden nicht definiertes Verhalten, und dass der code gegen eine Forderung des Standards.
Ich sehe nichts, das würde verbieten, eine Implementierung von Sie zu ignorieren. Auch wenn Sie nichts Tat, jedoch, wie Sie in der Spezifikation würde bedeuten, dass ein Programm, welches durchgeführt
printf("%hx",1u);
würde definiert haben, Verhalten; dagegen,, ohne text, der angibt, dass "h" war eine rechtliche Modifikator so ein Programm wäre, UB, wäre es nicht?InformationsquelleAutor Michael Burr
In
%...x
- Modus werden alle Werte interpretiert als unsigned. Negative zahlen sind deshalb so gedruckt, wie Ihre unsigned Konvertierungen. In der 2-Komplement-Arithmetik, die die meisten Prozessoren verwenden, gibt es keinen Unterschied in der bit-Muster zwischen ein signiertes negative Zahl, und seine positiven unsigned entspricht, die definiert ist durch modulo-Arithmetik (addition der maximale Wert für das Feld plus ein, um die negative Zahl ist, entsprechend dem C99-standard). Viele software - vor allem die debugging-code am ehesten verwenden%x
- macht die Stille Annahme, dass die bit-Darstellung einer signierten negativen Wert und seine unsigned cast ist der gleiche, gilt die nur auf eine 2-Komplement-Maschine.Die mechanik dieser Besetzung sind solche, die hexadezimalen Darstellungen von Wert immer bedeuten, möglicherweise ungenau, dass eine Zahl gerendert wurde in 2 ergänzen, solange es nicht einen Rand drücken Zustand, wo sich die verschiedenen integer-Darstellungen haben unterschiedliche Reichweiten. Dies gilt auch für die arithmetische Darstellungen, in denen der Wert 0 ist nicht dargestellt, mit dem binären Muster von allen 0s.
Einen negativen
short
angezeigt, als einunsigned long
im hexadezimalen wird daher auf jeder Maschine, aufgefüllt mitf
aufgrund der impliziten Zeichen-Erweiterung in der Förderung, dieprintf
gedruckt wird. Die Wert ist die gleiche, aber es ist wirklich optisch irreführend, da die Größe des Feldes, was auf eine erhebliche Menge an Bandbreite, die ist einfach nicht vorhanden.%hx
kürzt die angezeigten Darstellung, um dies zu vermeiden, Polsterung, genau so, wie Sie zu dem Schluss, Ihre real-world use-case.Das Verhalten von
printf
ist nicht definiert, wenn nach Ablauf einerint
außerhalb der Reichweite vonshort
, die gedruckt werden sollen alsshort
, aber die einfachste Implementierung von weitem einfach verwirft die high-bit durch ein raw niedergeschlagen, während also die Skillung nicht erfordern jedes spezifische Verhalten, so ziemlich jeder vernünftige Umsetzung wird nur führen Sie abschneiden. Es sind in der Regel bessere Möglichkeiten, das zu tun, obwohl.Wenn printf nicht-Polsterung Werte oder anzeigen unsigned Darstellungen der signierten Werte
%h
ist nicht sehr nützlich.%x
,%u
oder%o
) führt zu undefiniertem Verhalten. Auch, soweit ich das beurteilen kann, eine der konformen Umsetzung kann auch einfach ignorieren das Vorhandensein vonh
oderhh
modifier außer mit%n
.Wirft zwischen
(unsigned)
und(signed)
etwas in der gleichen Breite garantiert, dass keine tatsächlichen änderungen, die bit-Muster der Daten, nur die interpretation dieser Bitmuster. (Besetzungen, ändern Sie die Breite null sind-verlängert oder Zeichen-erweitert angebracht ist.)%x
definiert ist, um die Arbeit auf unsigned Werte, so dass Sie die ersten sind-Umwandlung von signed zu unsigned, das ändert keine Daten, sondern ändert die interpretation - in-Effekt, mit%x
mit einer negativen Zahl zeigt die bit-Muster. Und%x
ist ein integer-Typ, und dieh
Modifikator wird über die integer-Typen, also ich denke, dass es unterstützt.Ihre Informationen blatently falsch. C definiert Konvertierungen (implizite oder gegossen) in Bezug auf die Werte, nicht bit-Muster. Konvertierung zu unsigned-Typen sind definiert durch die Norm in einer Weise, die gleichwertig zu modularer Arithmetik. Konvertierungen in eine vorzeichenbehaftete Typen sind durch die Implementierung festgelegt, außer wenn der Wert passt in den Ziel-Typ, ohne änderung.
Meine Frage ist, über die Sprache C, nicht über was auch immer die Umsetzung. Und "indem
UINT_MAX
" ist falsch. Du hast vergessen das +1, bei anderen details. Sobald Sie es zu beheben, es wird gleichwertig mit modularer Arithmetik.Sie sind richtig ließ ich die +1; ich werde das beheben, wenn ich roll das update bis zur Antwort. Wie auch immer, ich denke, wir haben ziemlich deutlich herausgearbeitet, dass die praktische verwenden von
%hx
ist begrenzt, wennprintf
ist illegal benutzt (zur Darstellung einer signierten argument als unsigned, die in der Regel genommen, um sicher zu sein, aber ist nur sicher, auf der eine 2-Komplement-Maschine; das Ergebnis ist ziemlich viel kaputt-code gemeinsame Bibliotheken auf nicht-2 ' C-Maschinen), die macht es von Natur aus die Umsetzung-spezifisch. Rational, es gibt keine Besondere Verwendung für Sie, wenn die Konvertierung schon passiert in einem sehr eng rechtlichen Bereich.InformationsquelleAutor Adam Norberg
Die einzige Anwendung die mir einfällt, ist für die übergabe eines
unsigned short
oderunsigned char
und mit der%x
umwandlungsspezifikator. Sie können nicht einfach mit einem bloßen%x
- der Wert kann gefördert werden, umint
eher alsunsigned int
, und dann hast du Undefiniertes Verhalten.Ihre alternativen sind entweder explizit umgewandelt das argument
unsigned
; oder verwenden%hx
/%hhx
mit einem nackten argument.unsigned short
oderunsigned char
wird gefördertint
, es ist immer noch positiv, also C ist die Darstellung entsprechend der Darstellung fürunsigned
. Soweit ich weiß, Fehler Missverhältnis ist gültig in der variadischen Funktion Argumente und die Argumente von Funktionen ohne Prototypen, solange der Wert positiv ist, da ein Wert mit Vorzeichen. Sicherlich%x
soll die Arbeit mitint
Argumente, solange Sie positiv ist...Für Allgemeine variadischen Funktionen, Sie haben Recht - aber für den speziellen Fall der
printf
Familie, der standard gibtunsigned int
als Typ des Arguments zu%x
, und später, sagt "Wenn ein argument nicht den richtigen Typ für die entsprechende Konvertierung der Spezifikation, ist das Verhalten undefiniert." - was ich nicht glaube, können Sie übergeben Sie einint
.Interessant. Ich vermute, das ist unbeabsichtigt aber. Vielleicht sollte ich mich durch die standard-und sehen, ob es irgendwelche Beispiele wie
printf("%x", 1);
(die müssten1U
statt1
durch Ihre Argumentation).InformationsquelleAutor caf
Die Variable Argumente zu
printf()
et al werden automatisch gefördert, die über die Standard-Konvertierungen, so dass jedeshort
oderchar
Werte gefördert werden, umint
wenn die an die Funktion übergeben.In Abwesenheit des
h
oderhh
Modifikatoren, Sie müssten die Maske die Werte übergeben, um die richtigen Verhaltensweisen zuverlässig. Mit den Modifikatoren, die Sie nicht mehr haben, um Maske der Werte; dieprintf()
Umsetzung macht den job richtig.Speziell für das format
%hx
, wird der code innerhalbprintf()
etwas tun zu können:Ich bin munter unter der Annahme, dass
short
ist ein 16-bit-Menge, die der standard nicht wirklich garantieren, dass, natürlich.InformationsquelleAutor Jonathan Leffler
Fand ich es sinnvoll, zu vermeiden, casting, wenn die Formatierung unsigned chars zu hex:
Es ist nur eine kleine convenience-Kodierung, und sieht sauberer aus, als mehrere casts (IMO).
InformationsquelleAutor mzimmers
Ich Stimme mit Ihnen überein, dass es nicht unbedingt erforderlich ist, und so durch, dass die Vernunft alleine ist nicht gut in eine C-library-Funktion 🙂
Könnte es "nett" für die Symmetrie der verschiedenen Flaggen, aber es ist meistens kontraproduktiv, weil es versteckt die "Umstellung auf
int
" - Regel.InformationsquelleAutor Jens Gustedt
einem anderen Ort ist es praktisch, snprintf Größe überprüfen.
gcc7 Größe überprüfen Sie bei der Verwendung von snprintf
so wird dies scheitern
also es zwingt Sie dazu, größere char bei der Verwendung von %d wird bei der Formatierung eines char
hier ist ein Begehen, das zeigt die Updates, anstatt die Erhöhung der char-array Größe geändert %d %h. diese auch geben genauere Beschreibung
https://github.com/Mellanox/libvma/commit/b5cb1e34a04b40427d195b14763e462a0a705d23#diff-6258d0a11a435aa372068037fe161d24
-Wformat-overflow
Warnung, gcc-Dokumente, dass er der Auffassung, "Numerische Argumente, die bekannt sind, um gebunden werden zu einem Teilbereich Ihrer Art" das ist immer der Fall für geförderte chars. Aber Stufe 2 nicht beschreiben, dieses Verhalten...? gcc.gnu.org/onlinedocs/gcc/Warning-Options.htmlich arbeite mit libvma und wir schoben diese verpflichten zu kompilieren mit gcc7. ich bin mir nicht sicher, was überlauf Niveau, das wir verwendet haben (ich denke mal der Standard)
InformationsquelleAutor rafi wiener