Ein Argument an printf()
übergeben, das nicht mit den Formatbezeichnern in der Formatzeichenfolge übereinstimmt, ist undefiniertes Verhalten ... und mit undefiniertem Verhalten kann alles passieren und die Ergebnisse sind nicht notwendigerweise konsistent von einer Instanz zur anderen - also sollte es vermieden werden.
Warum sehen Sie einen Unterschied zwischen x86 (32-Bit) und x86-64, ist es wahrscheinlich aufgrund von Unterschieden in der Art, wie Parameter in jedem Fall übergeben werden.
im x86 Fall werden die Argumente printf()
wahrscheinlich auf dem Stapel geführt werden, ausgerichtet auf die 4-Byte-Grenzen - so dass, wenn der Prozesse printf()
%d
Spezifizierer liest eine 4-Byte-int
aus dem Stapel, die eigentlich die unteren 4 Bytes von a
. Da a
war 10 diese Bytes haben keine Bits gesetzt, so sind sie als int
Wert von 0.
Im x86-64 Fall interpretiert werden die Argumente zu printf()
alle in Registern übergeben (obwohl einige auf das sein würde Stack, wenn es genug von ihnen gab) ... aber double
Argumente werden in verschiedenen Registern als int
Argumente (wie% xmm0 statt% rsi) übergeben. Also, wenn printf()
versucht, ein int
Argument zu den %d
Spezifizierer zu verarbeiten, es dauert es von einem anderen Register, das die a
wurde übergeben, und verwendet, was Müll-Wert im Register anstelle der unteren Bytes von a
übrig gelassen wurde, und interpretiert das als etwas Müll int
Wert.
Es ist undefiniertes Verhalten, 'printf' mit Argumenten aufzurufen, die nicht mit der Formatzeichenfolge übereinstimmen. –
Nicht wirklich mein Bereich, aber es sieht so aus, als ob x86-64 'double' und' int' Argumente in verschiedenen Registern übergeben würden - also 'a' wird an' printf() 'an einer Stelle übergeben, aber bei der Verarbeitung der format string 'printf()' sucht nach einem 'int'-Argument in einem anderen Register, in dem kein Wert enthalten ist, da es nicht zur Übergabe eines Arguments verwendet wurde. – Dmitri