以下代码有效:
int main(void)
{
float f = get_float();
int i = round(f*100);
printf("%i\n", i);
}
然而,如果以这种方式编码会产生错误:
printf("%i\n", round(1.21*100));
输出结果显示round(1.21*100)
为float
。那么,为什么
int i = round(f*100);
很好吗?
答案 0 :(得分:15)
当你这样做时
int i = round(f*100);
您转换 double
函数round
的结果。转换后的结果存储在int
变量i
中,该变量可以与格式"%i"
一起使用,因为它需要int
参数。
当您将double
round
结果直接作为参数传递给期望int
的格式时,您的格式和参数类型不匹配。这会导致未定义的行为。
对printf
的调用未进行转换,因为printf
函数中的代码不知道实际的类型,因此无法进行转换 论点。它只知道格式"%i"
。变量参数函数会丢失所有可能的类型信息。
答案 1 :(得分:5)
这是因为自动类型转换的行为。在printf中,自动类型转换不起作用。当你说%i时,它只是期望整数,它不能将double转换为整数然后打印。
在赋值操作中,double首先转换为整数,然后将其赋值给=运算符的左操作数。我希望这会有所帮助。
答案 2 :(得分:4)
这有点重复,但可能有助于更好地理解:
round()
有以下原型:
double round(double x);
所以它返回double
。
C中有{em>隐式转换从double
到int
,所以写
int i = round(f*100);
会将round()
的结果转换为int
。
如果你有一个需要int的函数,例如
void printMyNumber(int number)
{
printf("%i\n", number);
}
你可以这样称呼它:
printMyNumber(round(f*100));
并且隐式转换按预期工作,因为编译器会看到两种类型(round()
的返回类型和printMyNumber()
的预期参数类型。)
这与printf()
无法合作的原因是printf()
的原型如下所示:
printf(const char *format, ...);
所以,除第一个参数外,参数的类型是 unknown 。因此,无论您传递的是什么都没有任何转换(default argument promotions除外)。当然,您可以使用强制转换来实现显式转换:
printf("%i\n", (int) round(f*100)); // <- this is fine