#include<stdio.h>
main()
{
float x=2;
float y=4;
printf("\n%d\n%f",x/y,x/y);
printf("\n%f\n%d",x/y,x/y);
}
输出:
0
0.000000
0.500000
0
使用gcc 4.4.3编译。 程序退出时出现错误代码12。
#include<stdio.h>
main()
{
float x=2;
float y=4;
printf("\n%d\n%f",x/y,x/y);
printf("\n%f\n%d",x/y,x/y);
}
输出:
0
0.000000
0.500000
0
使用gcc 4.4.3编译。 程序退出时出现错误代码12。
正如其他答案中所指出的那样,这是由于格式字符串与参数类型不匹配。
我猜测您在使用 x86(根据观察到的结果)。
参数通过堆栈传递,虽然 x/y
是 float
类型,但由于类型“提升”规则,将作为 double
传递给变参函数。
int
是一个32位的值,而 double
是一个64位的值。
在这两种情况下,您都会将 x/y
(= 0.5)传递两次。该值作为64位double
的表示形式为0x3fe0000000000000
。作为一对32位字,它存储为0x00000000
(最低有效32位)后跟0x3fe00000
(最高32位)。因此,在 printf()
中看到的堆栈上的参数如下:
0x3fe00000
0x00000000
0x3fe00000
0x00000000 <-- stack pointer
在你的两种情况中,%d
导致第一个 32 位值 0x00000000
被弹出并打印。 接下来,%f
弹出下两个 32 位值,即 0x3fe00000
(64 位 double
的最低有效 32 位)和随后的 0x00000000
(最高有效位)。 结果的 64 位值为 0x000000003fe00000
,解释为 double
后是一个非常小的数字。(如果你将格式字符串中的 %f
改为 %g
,你会发现它几乎为 0,但不完全是这样)。%f
正确地弹出第一个 double
,%d
弹出第二个 double
中的 0x00000000
半部分,因此它看起来可以工作。(const char *)
不会意外地将int
转换为指针。从语法上讲,这是可能的。 - Roland Illig是的。printf函数从可变参数列表中按照格式说明符读取顺序读取参数。
这两个printf语句都是无效的,因为您正在使用期望int的格式说明符,但您只提供了一个double。
您正在进行未定义的行为。您所看到的是巧合; printf
可以写入任何内容。
在给 printf
参数时必须匹配精确类型。例如,您可以进行强制转换:
printf("\n%d\n%f", (int)(x/y), x/y);
printf("\n%f\n%d", x/y, (int)(x/y));
这个结果并不让人意外,在第%d次中您传递了一个double类型的值,但实际上需要的是整型。
0dmckee@thorin$
作为我的提示,以及在输出开头添加了一个完全不必要的额外行。在中间放置尽可能多的换行符,当需要更清晰的循环编码时使用前导换行符,但是在等效时首选结束换行符而不是前导换行符。 - dmckee --- ex-moderator kitten