Это неопределенное поведение (UB), поскольку существует несоответствие между строкой формата и аргументом.Сказав это, и предположив, что компилятор не выполняет некоторые нетривиальные преобразования, тогда UB имеет некоторое типичное поведение в этом случае.
Чтобы увидеть, что происходит, вы должны проверить соглашение о вызовах в системе.Скорее всего, программа работает на 64-битной архитектуре x86, которая передает аргументы в соответствии с соглашениями о вызовах X86 .В окнах первое значение с плавающей запятой передается другим регистром (XMM0), чем целочисленный аргумент (один из RCX, RDX, R8, R9).Это означает, что для:
printf( "with the d a = %d \n", b);
double b
передается в одно место, а "%d"
читает из другого.Также обратите внимание, что соответствующие целые числа считаются энергозависимыми и могут быть сброшены при более раннем вызове printf
.Это означает, что int (a = 2), переданный предыдущему printf
через регистр, уничтожается тем же printf
.По сути, «% d» заставляет printf
прочитать значение барахла, оставшееся от внутренней реализации printf
.
В результате в Linux и на Mac с помощью clang и gcc я получаю случайное значение барахла вместо нуля.Я предполагаю, что исходный вопрос относится к Visual Studio в Windows, которая может установить целое число в ноль в режиме отладки (или что-то подобное).
Обратите внимание, что нет гарантии с неопределенным поведением.Компилятор может сделать что-нибудь, включая удаление ошибочной строки или что-то совершенно неожиданное.Анализ этого ответа является правильным для данного компилятора, системы и уровня оптимизации.Это наблюдалось в сгенерированной сборке, но любое незначительное изменение (даже в другой функции в коде) может привести к совершенно другому поведению.Никогда не полагайтесь на неопределенное поведение.