结果
printf("%d\n", 5.0 + 2);
是0
但是
int num = 5.0 + 2;
printf("%d\n", num);
是7
两者之间有什么区别?
答案 0 :(得分:9)
5.0 + 2
的结果为7.0
,类型为double
。
"%d"
格式将打印int
。
格式规范和参数类型不匹配会导致不确定的行为。
要使用printf
打印float
或double
值,应使用格式"%f"
。
使用
int num = 5.0 + 2;
您将5.0 + 2
的结果转换为int
值7
。然后,使用正确的格式说明符打印int
值。
答案 1 :(得分:6)
在所有表达式中,每个操作数都有一个类型。 5.0
的类型为double
。 2
的类型为int
。
每当将double和整数用作同一运算符的操作数时,在计算之前,该整数将被静默转换为double。结果的类型为double
。
因此您将double
传递给printf
,但是由于使用了int
,因此您已经告诉它期望%d
。结果是错误,结果未定义。
但是对于int num = 5.0 + 2;
,您首先得到的结果为double
,7.0
。然后,将转换强制返回到int
。该代码等效于:
int num = (int)((double)5.0 + (double)2);
此处有更多详细信息:Implicit type promotion rules
答案 2 :(得分:3)
表达式5.0 + 2
的结果为double
类型,因为此处的运算符+
的两个操作数中至少有一个是浮点数/双精度值(因此另一个将是在添加之前将其转换为double
。
如果您写printf("%d\n", 5.0 + 2)
,则将在格式说明符实际期望int
的地方传递一个浮点值。这种不匹配是不确定的行为,您收到的0
也可能是其他东西(另一个数字,一个崩溃,一个....等等)。
int num = 5.0 + 2
会将double
产生的5.0 + 2
值转换回整数值(舍弃任何小数部分)。因此num
的值为7
,并且由于num
是整数类型,因此与格式说明符%d
一起有效。
答案 3 :(得分:1)
5.0+2
键入double
。
针对的编译器警告
int main() { return _Generic(5.0 + 2, struct foo: 0); }
应该告诉您是否
int main() { return _Generic(5.0 + 2, double: 5.0+2); }
没有错误的编译不会。
将"%d"
与double
中的printf
匹配会导致不确定的行为。
任何结果都是合法的,包括擦除硬盘驱动器(除非您的程序已经在其中某处具有这种功能,否则不太可能发生;如果这样做,UB很可能会导致它被无意中调用)。
答案 4 :(得分:0)