Ваша программа вызывает неопределенное поведение, потому что типы аргументов printf()
не соответствуют ожидаемым printf.Нет никакого способа предсказать результат, глядя на исходный код.
C99-TC3, §7.19.6.1/9
Если какой-либо аргумент не является правильным типом для соответствующей спецификации преобразования, поведение не определено.
Однако, если вас интересует причина, по которой вы наблюдаете поведение, то, скорее всего, ваш компилятор является одним из тех, которые передают значения с плавающей запятой в printf () в регистрах ЦП с плавающей запятой.(GNU и CLang делают это, например).Второй вызов printf поместил разыменованное значение в регистр с плавающей запятой, но printf
, увидев спецификатор преобразования %s
, посмотрел на регистр, где должен был быть передан char*
, вероятно, регистр общего назначения,который оказался нулевым в вашем случае.
PS: Вот что GCC 4.6.1 делает из этого на моем linux
main:
pushq %rbx
leal .LC0(%rip), %ebx
movl $.LC1, %esi
subq $16, %rsp
movl %ebx, %edx
movl $1, %edi
movq $.LC0, 8(%rsp)
xorl %eax, %eax
call __printf_chk
movd %ebx, %xmm0
movl $.LC1, %esi
movl $1, %edi
movl $1, %eax
unpcklps %xmm0, %xmm0
cvtps2pd %xmm0, %xmm0 # this is where your value went
call __printf_chk # is NOT gonna read from xmm0!
addq $16, %rsp
xorl %eax, %eax
popq %rbx
ret
Та же история с clang 2.9
...
movl $.L.str, %ebx
xorb %al, %al
movl $.L.str1, %edi # .L.str1 is your format "%s\n"
movl $.L.str, %esi # .L.str is your static "string"
callq printf
movd %ebx, %xmm0 # your value is in xmm0 again
cvtss2sd %xmm0, %xmm0 # promoted to double, but still in xmm0
movb $1, %al
movl $.L.str1, %edi
callq printf # printf has no idea