Ist es illegal, die Modifikatoren h oder hh length zu verwenden, wenn das entsprechende Argument für printf kein short / char ist?

9

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 ein hh oder d -Argument angewendet wird (Das Argument wird gemäß den Integer-Promotions hochgestuft, aber sein Wert muss vor dem Drucken in i oder o konvertiert werden); oder dass ein folgender u 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 ein X oder signed char -Argument angewendet wird (Das Argument wird gemäß den Integer-Promotions hochgestuft, aber sein Wert muss vor dem Drucken in unsigned char oder signed char konvertiert werden); oder dass ein folgender unsigned char Konvertierungsspezifikator auf einen Zeiger auf ein kurzes n 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 ?

  • In dieser Antwort wird behauptet, dass ein Argument übergeben wird, das außerhalb des Bereichs von 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.
  • Ich behaupte, dass die Funktion für jeden Wert des Typs 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.
  • Man könnte auch behaupten, dass das Aufrufen der Funktion mit einem Argument, das nicht dem entsprechenden Typ vor der Standard-Argument-Heraufstufung entsprach, ein undefiniertes Verhalten ist, aber dies scheint abstrus.

Welche dieser drei Interpretationen von §7.21.6.1¶7 (wenn überhaupt) ist richtig?

    
fuz 11.09.2015, 17:41
quelle

1 Antwort

4

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.

    
John Bollinger 11.09.2015, 18:05
quelle