Ich arbeite an einem 32-Bit-System. Wenn ich versuche, mehr als einen 64-Bit-Wert in einem einzelnen Druck zu drucken, kann er keine weiteren (d. H. Zweiten, dritten, ...) Variablenwerte drucken.
Beispiel:
%Vor%Warum kann dieser Druck nicht alle Werte drucken?
Ich ändere meine Frage
%Vor%mit diesem Ergebnis ist: a ist 12345678 & amp; b ist 8765432100000000 & amp; c ist 1111111100000000
Wenn ich einen Wert nicht richtig ausdrücke, warum ändern sich dann die Werte des anderen?
Sie sollten die in <inttypes.h>
Es ist hässlich, aber es ist tragbar. Dies wurde in C99 eingeführt, also benötigen Sie einen C99-kompatiblen Compiler.
Es werden alle auf meinem Computer gedruckt, aber es gibt drei Kompilierungswarnungen, da %llx
eine long long unsigned int
erwartet.
Sind Sie sicher, dass Sie 64-Bit-Typen verwenden müssen? Alle drei Hexcodes sind nur 32 Bit. Vielleicht könnten Sie einfach 32 Bits verwenden und tun:
%Vor%(Oder verwenden Sie das Stdint-Äquivalent von 32bit unsigned int)
Es sei denn, Sie benötigen 64 Bits, damit Sie später weitere Bits hinzufügen können.
Wie für ein Forum mit dem Namen Stapelüberlauf angezeigt, ist die Ursache für die unerwartete Ausgabe von printf()
auf Stapelfehlstellungen zurückzuführen. Die Größenabweichung zwischen der Konvertierungsspezifikation %x
und dem Funktionsargument a
verursacht die Fehlausrichtung.
Beim Kompilieren der Anweisung
%Vor%Der Compiler generiert Maschinencode, der die Funktionsargumente auf dem Stapel in der Reihenfolge von rechts nach links verschiebt.
Der Compiler verwendet die Variablendeklarationen, nicht die Formatzeichenfolge, um die Datengröße jedes Arguments auf dem Stapel zu bestimmen (außer möglicherweise zum Generieren von Warnungen). In einer x86-CPU (wie bei den meisten Maschinen) wird der Stapelzeiger bei jedem Drücken dekrementiert. Beim Eingeben der Bibliotheksfunktion printf()
hat der Stapel daher das folgende Layout:
Die Top-of-Stack-Adresse von 0084 ist für dieses Beispiel beliebig.
Da alle drei Variablen als uint64_t
deklariert sind, verschiebt der kompilierte Code diese Variablen im Stack als 64-Bit-Werte. Bei einer Little-Endian-Maschine wie einer x86-CPU landen die High-Bytes jedes uint64
-Werts in den höheren Adressen.
Die Implementierung von printf()
verwendet die Formatzeichenfolge, um die Anzahl und die Größe der Argumente auf dem Stapel zu bestimmen. Im Gegensatz zum Compiler erhält printf()
keine Informationen über die ursprünglichen Variablendeklarationen. Die erste Konvertierungsspezifikation lautet %x
. Daher erwartet printf()
a
als 32-Bit-Wert und analysiert daher printf()
das Stack-Layout wie folgt:
Die Stapelfehlausrichtung erklärt, warum a
12345678 wie erwartet ausgibt, aber b
und c
wurden effektiv um 32 Bit nach 8765432100000000 und 1111111100000000 nach links verschoben.
Das Korrigieren der ersten %x
Konvertierungsspezifikation oder des Casting Arguments a
auf uint32 sollte das Problem beheben.