printf-format für 1-byte-Zahl unterzeichnet
Vorausgesetzt, die folgenden:
sizeof(char) = 1
sizeof(short) = 2
sizeof(int) = 4
sizeof(long) = 8
Den printf
format für ein 2-byte-Zahl unterzeichnet ist %hd
für ein 4 byte signed-Zahl %d
für ein 8-byte-Zahl unterzeichnet ist %ld
, aber was ist das richtige format für ein 1-byte-Zahl unterzeichnet?
- FYI:
sizeof(char)
ist definiert in der Spezifikation immer1
egal, die tatsächliche Größe deschar
. - Gibt es etwas falsch mit der Förderung einer
int
und nur mit%d
? - Für Ihre Frage, die Sie vielleicht Lesen möchten, z.B. dieser Verweis.
- Ich dachte, dass alles, was kürzer ist als ein int wird in einen int (oder uint, wenn unsigned), wenn etwas in den stack übergeben printf(), also, was ist der nutzen von
h
undhh
? - Gute Frage. Die Antwort scheint unklar.
- Förderung
int
tut Zeichen Erweiterung (wennchar
signiert ist) , so z.B.0xf0
wird0xfffffff0
was nicht ganz das gleiche wie0xf0
..
Du musst angemeldet sein, um einen Kommentar abzugeben.
%hh
- und die integer-Konvertierung Planer Ihrer Wahl (zum Beispiel%02hhX
. Finden Sie in der C11-standard §7.21.6.1p5:Den in Klammern gesetzten Kommentar ist wichtig. Da der integer-promotions auf die Argumente, die variadischen Funktionen (wie
printf
), die Funktion sieht nie einchar
argument. Viele Programmierer denken, dass das bedeutet, dass es unnötig ist zu verwendenh
undhh
Qualifikation. Sicherlich, Sie sind nicht die Schaffung Undefiniertes Verhalten verlassen, Sie aus, und die meiste Zeit es wird funktionieren.Jedoch
char
können nun unterzeichnet werden, und die integer-promotion bewahren deren Wert, und macht es in eine Ganzzahl. Drucken der signed integer mit einer unsigned-format (wie%02X
) stellen Sie mit dem Vorzeichen erweitertF
s. Also, wenn Sie anzeigen möchten, unterzeichnetchar
mit einem unsigned-format, die Sie benötigen, zu sagenprintf
was die ursprüngliche unpromoted Breite der integer-Typ war, mithh
.Im Falle, dass war nicht klar, ein einfaches Beispiel (ist aber umstritten) Beispiel:
Ausgabe:
In den Kommentar-thread, es ist (oder möglicherweise war) erhebliche Diskussion darüber, ob das obige snippet ist Undefiniertes Verhalten, weil die
X
format-Spezifikation erfordert eine unsigned-argument, in der Erwägung, dass diechar
argument ist (zumindest auf der Umsetzung mit der Herstellung der vorgestellten Ausgabe) unterzeichnet. Ich denke, dieses argument stützt sich auf §7.12.6.1/p9: "Wenn ein argument nicht den richtigen Typ für die entsprechende Konvertierung der Spezifikation, ist das Verhalten undefiniert."Jedoch, im Fall von
char
(undshort
) integer-Typen, die Ausdruck in der Argumentliste gefördertint
oderunsigned int
bevor die Funktion aufgerufen wird. (Es ist erwähnenswert, dass auf den meisten Architekturen, alle drei Charakter-Typen gefördert werden, um eine signierteint
; Förderung einerunsigned char
(oder unsignedchar
) zu einerunsigned int
wird nur geschehen, auf eine Umsetzung, wosizeof(int) == 1
.)Also auf den meisten Architekturen, das argument einer
%hx
oder eine%hhx
format-Konvertierung unterzeichnet werden, und nicht ein Undefiniertes Verhalten, ohne die Darstellung der Verwendung dieser format-codes sinnlos.Darüber hinaus, die der standard nicht sagen, dass
fprintf
(und Freunde) irgendwie wiederherstellen der ursprünglichen expression. Was Sie sagt, ist, dass der Wert "werden umgewandelt signed char oder unsigned char vor dem drucken" (§7.21.6.1/p5, oben zitiert, Hervorhebung Hinzugefügt).Umwandlung von einem Wert mit Vorzeichen in einen unsigned-Wert ist nicht undefiniert. Es ist auch nicht zu unbestimmten oder von der Implementierung abhängig. Es besteht lediglich aus (begrifflich) "mehrfach addieren oder subtrahieren von eins mehr als der maximale Wert, der dargestellt werden kann und die neue Art, bis der Wert im Bereich des neuen Typs." (§6.3.1.3/p2)
Also es ist eine gut definierte Verfahren zum konvertieren der argument Ausdruck ein (eventuell signierten)
int
argument, und eine gut definierte Verfahren für die Umwandlung, die Wert auf eineunsigned char
. Ich also argumentieren, dass ein Programm wie die, die oben präsentiert ist ganz gut definiert.Für die Bestätigung, das Verhalten von
fprintf
angegebenen Formatbezeichner%c
ist wie folgt definiert (§7.21.6.8/p8), Hervorhebung Hinzugefügt:Wenn man die vorgeschlagenen restriktiven interpretation, das macht das obige Programm nicht definiert, dann glaube ich, dass man gezwungen wäre, zu argumentieren, dass:
war auch UB. Ich glaube jedoch, dass fast jeder C-Programmierer geschrieben hat, etwas ähnlich, dass, ohne zu denken, zweimal über es.
Den wichtigsten Teil der Frage ist, was ist gemeint mit "argument" in §7.12.6.1/p9 (und andere Teile des §7.12.6.1). Der C++ - standard ist etwas genauer; es gibt an, dass wenn ein argument ist, unterliegen die default argument promotions "der Wert des Arguments konvertiert wird gefördert geben, bevor der Anruf", die ich so interpretieren, dass, wenn man den Anruf (Z. B. die call of
fprintf
), die Argumente sind jetzt die beworbenen Werte.Ich glaube nicht, dass C tatsächlich anders, zumindest in Absicht. Er verwendet Formulierungen wie "die Argumente&hellips; gefördert werden", und an mindestens einer Stelle "das argument nach der promotion". Weiterhin wird in der Beschreibung von variadischen Funktionen (die
va_arg
makro, §7.16.1.1), die Einschränkung auf den Argumenttyp versehen beiläufig "der Typ der die tatsächliche nächste argument (als gefördert nach der default argument promotions)".Werde ich frei Stimmen zu, dass alle diese (eine) subtile Lesen der unzureichend präzisen Sprache, und (b) zählen dancing angels. Aber ich sehe keinen Wert in der Deklaration, die standard-Verwendungen wie die Verwendung von
%c
mitchar
Argumente sind "technisch" UB; denaturiert, dass das Konzept der UB und es ist schwer zu glauben, dass ein solches Verbot wäre absichtlich, das führt mich zu glauben, dass die Auslegung nicht beabsichtigt war. (Und, vielleicht, sollte korrigiert werden redaktionell.)--std=c11
%hhu
hat praktischen Wert auf Systemen mitsizeof(int) == 1
gcc -Wall -Wextra -pedantic -std=c99
mit gcc 4.8.2. ideone behauptet zu haben, 4.9. Sie müssen also, um genauer zu sein über Ihre-Umgebung-compiler-version und die compiler-Optionen.X
) - einschließlichhh
nicht entfernen Sie die UBlimits.h
.char
wird gefördertint
und dann inunsigned char
.char c = ...; int i = c; unsigned char d = i;
ist völlig legal, nicht?int
auch für%c
. Es heißt nicht "das argument, die (nach Anwendung der default argument promotions)" oder etwas ähnliches. 3.3/1 definiert den Begriff "argument" als Ausdruck, angezeigt in der Funktion aufrufen, die einechar
in diesem Fall.