我在玩C; 看一下这个:
#include <stdio.h>
#include <stdlib.h>
void main() {
printf("%d\n", 1.5);
printf("%f", 0);
}
Run Code Online (Sandbox Code Playgroud)
我期待输出:
0
0.000000
Run Code Online (Sandbox Code Playgroud)
但它打印:
0
1.500000
Run Code Online (Sandbox Code Playgroud)
第一次printf()通过1.5第二次printf()吗?
PS:我知道(%d对于整数,%f浮标).正如我所提到的,我只是在搞乱代码.
PS2:我正在使用DevC++和Code :: Blocks.
chq*_*lie 13
根据C标准,行为未定义,以下是您系统上可能发生的情况:
printf("%d\n", 1.5); main将浮点值1.5作为第一个XMM寄存器中的double 传递并调用printf().printf()不修改XMM寄存器,因为如果不执行任何浮点操作来处理格式"%d".它从不同的地方检索要打印的值:寄存器或堆栈,这个值恰好是0.printf("%f", 0);,main不会更改XMM,因为它通过其他位置,寄存器或堆栈传递int值0.printf()最终从之前存储的XMM寄存器中获取double格式的值.因此输出.%f1.51.500000以上都不能以任何方式得到保证,但这可能是您感兴趣的解释.不同的系统可能以不同的方式处理参数传递,它们是ABI(应用程序二进制接口)的一部分.
只是为了好玩,您可能想尝试这种变化:
printf("first %d, second %f\n", 1.5, 42);
Run Code Online (Sandbox Code Playgroud)
在我的系统输出 first 42, second 1.500000
你有一些未定义的行为(所以可能发生任意不好的事情,你不应该期待任何好事).随着对的printf函数期望(注意,当作为参数传递一个被晋升为一个),但是是文字型的.此外,不同的编译器(甚至同一编译器的不同版本)或不同的优化标志可能会产生不同的不良影响.%fdoublefloatdouble0int
请阅读Lattner的博客,了解What Every C程序员应该了解的未定义行为.
(对未定义行为的良好态度是努力总是避免它;不要浪费时间去试图理解具体发生的事情;但是将UB视为非常肮脏或" 生病 "的东西,你总是避免)
要解释观察到的行为,您需要深入了解特定实现的细节,特别是ABI和调用约定(对于可变函数àla printf).另外,查看生成的汇编代码(使用GCC,编译gcc -fverbose-asm -S -O1); 有可能在一个不同于一个参数的寄存器(或一些调用堆栈槽)中传递一个double参数int(因此该printf函数正在使垃圾发生在该位置或寄存器中); 另请注意,通常sizeof(int)可能是4但sizeof(double)可能是8(因此数据量甚至不对).
为了避免这种错误,需要有良好的编译器(如编译的习惯GCC或锵/ LLVM在免费软件领域),并启用所有警告和调试信息(例如,编译使用gcc -Wall -Wextra -g与GCC).编译器会警告你.
BTW,void main()是非法的.它至少应该是int main(void)优选的int main(int argc, char**argv),你应该注意这些论点.
在您的示例中,gcc -Wall -Wextra(使用GCC 7)告诉(对于您的源文件april.c):
april.c:4:10: warning: return type of ‘main’ is not ‘int’ [-Wmain]
void main() {
^~~~
april.c: In function ‘main’:
april.c:5:14: warning: format ‘%d’ expects argument of type ‘int’,
but argument 2 has type ‘double’ [-Wformat=]
printf("%d\n", 1.5);
~^
%f
april.c:6:14: warning: format ‘%f’ expects argument of type ‘double’,
but argument 2 has type ‘int’ [-Wformat=]
printf("%f", 0);
~^
%d
Run Code Online (Sandbox Code Playgroud)
注:开发-C++和代码块都没有编译器,但IDE秒.它们都运行一些外部 编译器(可能是GCC作为系统上的MinGW).