#include<stdio.h>
#define square(x) x*x
void main()
{
int i;
i = 8 / square(4);
printf("%d %d", i, 8/square(4));
}
输出:8 8
但如果我写下面的代码:
#include<stdio.h>
#define square(x) x*x
void main()
{
float i;
i = 8 / square(4);
printf("%f %f", i, 8/square(4));
}
提供输出:8.000000 0.000000
为什么这样?请解释
问题不仅在于格式说明符,还在于您定义宏的方式。它应该是:
#define square(x) ((x)*(x))
宏也不是类型安全的。现在,如果你投射你的结果你会看到发生了什么,因为4的平方是16和8/16是0.5它被截断到int
因此变为0.对于正确的值,这是你应该如何类型转换:
printf("%d %d", (int)i, (int)(8/square(4)));
printf("\n%f %f", (float)i, (float)8/((float)square(4)));
0 0
0.000000 0.500000
首先纠正这个:
#define square(x) x*x
至
#define square(x) ((x)*(x))
宏替换后的正确结果。
现在,在你的第一个程序中,正如其他人解释的那样,你使用了错误的格式说明符%f
来打印一个整数(8/(square(4)
将评估为整数),这是未定义的行为。
在第二个程序中,8/square(4)
的类型被提升为float
,因为你将结果存储在float i
中。因此,您在第一次打印时会得到8.000000
。在第二次打印时,由于与上述相同的原因,结果是错误的。
第一个很容易理解所以我只专注于第二个。您使用%f作为第二个参数,它需要一个浮点数,而C编译器将8 / square(4)作为整数。这种不匹配会破坏您的结果。
8/square(4)
导致int
并尝试使用%f
打印整数是Undefined behavior。因此,没有使用调试第二种情况下的值。
如果您正在使用gcc编译器,那么命令cc -E filename.c
可能会澄清您的疑虑。
这是因为你在第二个程序中给了float作为数据类型。
8 / square(4)将给出整数结果,因此您的输出会出错。你使用%f来打印一个整数。
那很简单......
因为%f表示数字的类型是double和默认精度