Die Funktionsfamilie printf
stellt eine Reihe von Längenmodifikatoren bereit, von denen zwei hh
(ein signed char
oder unsigned char
ein Argument, das auf int
hochgestuft ist) und h
(bezeichnet ein% co_de) darstellen % oder signed short
Argument wird auf unsigned short
) hochgestuft. In der Vergangenheit wurden diese Längenmodifikatoren nur eingeführt, um Symmetrie mit den Längenmodifikatoren von int
zu erzeugen, und werden selten für scanf
verwendet.
Hier ist ein Auszug aus ISO 9899: 2011 §7.21.6.1 "Die Funktion fprintf" ¶7:
7 Die Längenmodifikatoren und ihre Bedeutungen sind:
printf
Gibt an, dass ein folgender% -Co_de%,% Co_de%,% Co_de%,% Co_de%,% Co_de% oder% Co_de% -Konvertierungsspezifizierer auf einhh
oderd
-Argument angewendet wird (Das Argument wird gemäß den Integer-Promotions hochgestuft, aber sein Wert muss vor dem Drucken ini
odero
konvertiert werden); oder dass ein folgenderu
Konvertierungsspezifizierer auf einen Zeiger auf ein signiertes Zeichen angewendet wird Argument.
x
Gibt an, dass ein folgender% -Co_de%,% Co_de%,% Co_de%,% Co_de%,% Co_de% oder% Co_de% -Konvertierungsspezifizierer auf einX
odersigned char
-Argument angewendet wird (Das Argument wird gemäß den Integer-Promotions hochgestuft, aber sein Wert muss vor dem Drucken inunsigned char
odersigned char
konvertiert werden); oder dass ein folgenderunsigned char
Konvertierungsspezifikator auf einen Zeiger auf ein kurzesn
Argument angewendet wird....
Wenn der Fall des Konvertierungsbezeichners h
ignoriert wird, was sagen diese fast identischen Absätze über das Verhalten von d
und i
?
o
,% liegt. co_de%, u
oder x
bzw. für eine Conversion-Spezifikation mit einem X
oder short int
length modifier bzw. ist undefiniertes Verhalten, da das Argument nicht vom Typ unsigned short int
, short int
, etc. konvertiert wurde. vorher. unsigned short int
wohldefiniert funktioniert und dass sich n
so verhält, als wäre der Parameter in int
, n
, etc. konvertiert worden. vor der Konvertierung. Welche dieser drei Interpretationen von §7.21.6.1¶7 (wenn überhaupt) ist richtig?
Der Standard spezifiziert:
Wenn ein Argument nicht der richtige Typ für die entsprechende Konvertierungsspezifikation ist, ist das Verhalten nicht definiert.
[C2011 7.21.6.1/9]
Was mit "der richtige Typ" gemeint ist, ist denkbar offen für Interpretationen, aber die plausibelste Interpretation ist für mich der Typ, auf den die Konversionsspezifikation sich bezieht, wie zuvor im selben Abschnitt spezifiziert und zitiert Teil, in der Frage. Ich nehme die Klammern Kommentare zur Argument-Promotion, um die normalen Regeln für das Übergeben von Argumenten zu erkennen und zu vermeiden, dass diese Funktionen Sonderfälle sind. Ich halte die Klammern nicht für relevant, um den "richtigen Typ" des Arguments zu bestimmen.
Was tatsächlich passiert, wenn Sie ein breiteres Argument übergeben, als für die Konvertierungsspezifikation korrekt ist, ist eine andere Frage. Ich bin geneigt zu glauben, dass das C - System von niemandem so implementiert wird, dass es einen Unterschied macht, ob ein printf()
- Argument tatsächlich ein char
ist, oder ob es ein int
ist, dessen Wert im Bereich von %Code%. Ich behaupte jedoch, dass es für den Compiler ein gültiges Verhalten ist, die Übereinstimmung des Argumenttyps mit dem Format zu überprüfen und das Programm bei einer Nichtübereinstimmung abzulehnen (weil das erforderliche Verhalten in einem solchen Fall explizit nicht definiert ist).
Andererseits könnte ich mir sicherlich char
Implementierungen vorstellen, die sich tatsächlich schlecht benehmen (Müll drucken, Speicher korrumpieren, Mittag essen), wenn der Wert eines Arguments außerhalb des Bereichs liegt, der durch den entsprechenden Konvertierungsspezifizierer impliziert wird. Dies ist auch zulässig, weil das Verhalten nicht definiert ist.
Tags und Links c undefined-behavior language-lawyer printf short