Передача аргумента printf()
, который не соответствует спецификаторам формата в строке формата, является неопределенным поведением ... и с неопределенным поведением может произойти что-либо, и результаты не обязательно согласованы из одного экземпляра в другой - поэтому его следует избегать.
Что касается того, почему вы видите разницу между x86 (32-разрядной) и x86-64, это, вероятно, связано с различиями в способе передачи параметров в каждом случае.
В случае x86, аргументы printf()
, вероятно, передается на стек, выровнены по границам 4-байтовых - поэтому, когда printf()
обрабатывает %d
спецификатор считывает 4 байта int
из стека, которая на самом деле нижние 4 байта от a
. Поскольку a
было 10 эти байты не не бит установлен, поэтому они интерпретируются как int
значение 0.
В x86-64 случае аргументы printf()
все передаются в регистрах (хотя некоторые бы на стек, если их было достаточно) ... но double
аргументы передаются в разных регистрах, чем int
аргументы (например,% xmm0 вместо% rsi). Поэтому, когда printf()
пытается обработать аргумент int
для соответствия спецификатору %d
, он принимает его из другого регистра, который был передан одним a
, и использует все остальное значение мусора в регистре, а не нижние байты a
, и интерпретирует это как какой-то фигня int
значение.
Неопределенное поведение для вызова 'printf' с аргументами, которые не соответствуют строке формата. –
Не моя область, но она похожа на x86-64 аргументы 'double' и' int' передаются в разных регистрах, поэтому 'a' передается' printf() 'в одном месте, но при обработке format string 'printf()' ищет аргумент 'int' в другом регистре, который содержит мусор, поскольку он не использовался для передачи аргумента. – Dmitri