为什么printf的打印带有浮点和整数格式说明符的随机值 [英] Why does printf print random value with float and integer format specifier

查看:180
本文介绍了为什么printf的打印带有浮点和整数格式说明符的随机值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个简单的code在64位计算机上

I wrote a simple code on a 64 bit machine

int main() {
    printf("%d", 2.443);
}

所以,这是编译器将如何表现。它将确定的第二个参数是一个双重因此它将推堆栈8字节或者可能只使用寄存器在调用访问的变量。 %d个预计4字节整数值,因此它打印一些垃圾值。

So, this is how the compiler will behave. It will identify the second argument to be a double hence it will push 8 bytes on the stack or possibly just use registers across calls to access the variables. %d expects a 4 byte integer value, hence it prints some garbage value.

有趣的是,该值印变化,每次我执行这个程序。那么,什么是怎么回事?我预计它每次打印相同价值的垃圾不是每次不同的。

What is interesting is that the value printed changes everytime I execute this program. So what is happening? I expected it to print the same garbage value everytime not different ones everytime.

推荐答案

这是不确定的行为,当然,传递不对应的格式参数,所以语言不能告诉我们为什么输出的变化。我们必须着眼于实现,有什么code它产生的,也可能是操作系统了。

It's undefined behaviour, of course, to pass arguments not corresponding to the format, so the language cannot tell us why the output changes. We must look at the implementation, what code it produces, and possibly the operating system too.

我的设置是不同的,从你的,

My setup is different from yours,

Linux的3.1.10-1.16桌面x86_64的GNU / Linux操作系统(openSUSE的12.1)

Linux 3.1.10-1.16-desktop x86_64 GNU/Linux (openSuSE 12.1)

用gcc-4.6.2。但它是非常相似,它的合理怀疑相同的机制。

with gcc-4.6.2. But it's similar enough that it's reasonable to suspect the same mechanisms.

看着生成的汇编( -O3 ,出于习惯),相关部分()是

Looking at the generated assembly (-O3, out of habit), the relevant part (main) is

.cfi_startproc
subq    $8, %rsp             # adjust stack pointer
.cfi_def_cfa_offset 16
movl    $.LC1, %edi          # move format string to edi
movl    $1, %eax             # move 1 to eax, seems to be the number of double arguments
movsd   .LC0(%rip), %xmm0    # move the double to the floating point register
call    printf
xorl    %eax, %eax           # clear eax (return 0)
addq    $8, %rsp             # adjust stack pointer
.cfi_def_cfa_offset 8
ret                          # return

如果代替双击,我路过一个 INT ,没有太大的变化,但显著

If instead of the double, I pass an int, not much changes, but that significantly

movl    $47, %esi            # move int to esi
movl    $.LC0, %edi          # format string
xorl    %eax, %eax           # clear eax
call    printf

我已经看过了产生code的类型和传递给参数数量很多变化的printf ,并持之以恒,第一个(或晋升浮动)参数在 xmmN 过去了, N = 0,1,2 ,和整数( INT 字符,无论带符号的)在 ESI EDX , ECX r8d r9d ,然后堆栈

I have looked at the generated code for many variations of types and count of arguments passed to printf, and consistently, the first double (or promoted float) arguments are passed in xmmN, N = 0, 1, 2, and the integer (int, char, long, regardless of signedness) are passed in esi, edx, ecx, r8d, r9d and then the stack.

所以,我大胆的猜测,的printf 查找宣布 INT ESI ,并打印无论发生什么事在那里。

So I venture the guess that printf looks for the announced int in esi, and prints whatever happens to be there.

无论 ESI 的内容都在没事的时候在移动有什么办法predictable主,和他们可能意味着,我不知道。

Whether the contents of esi are in any way predictable when nothing is moved there in main, and what they might signify, I have no idea.

这篇关于为什么printf的打印带有浮点和整数格式说明符的随机值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆