为什么(double + int)的结果为0(C语言)

5

result of

printf("%d\n", 5.0 + 2);

is 0

but

int num = 5.0 + 2;
printf("%d\n", num);

是7

这两者之间有什么区别?


1
请参考这个答案,它会更有帮助 https://dev59.com/pGox5IYBdhLWcg3wsGaC#9027033 - Janith Udara
5个回答

9
< p > 5.0 + 2 的结果是 7.0,类型为 double

"%d" 格式用于打印 int

格式说明符和参数类型不匹配会导致未定义的行为

要使用printf打印floatdouble值,应使用格式"%f"


使用

int num = 5.0 + 2;

你需要将 5.0 + 2 的结果转换为 int7。然后使用正确的格式说明符打印出这个 int 值。

printf("%d\n", 1.1 ); 的结果是垃圾值。printf("%d\n", 5.0 ); 的结果是0。这两者之间有什么区别呢?非常感谢您的回复。 - PWS
2
@PWS - 0不是垃圾。未定义就是未定义,没有其他解释。 - StoryTeller - Unslander Monica
2
@PWS 不是“垃圾”,只是不符合你的预期。正如所提到的,格式和参数类型不匹配会导致未定义行为,理论上可能会召唤鼻妖或重新格式化您的硬盘。 - Some programmer dude

6

在所有表达式中,每个操作数都有一个类型。 5.0 的类型是 double2 的类型是 int

无论何时,当一个双精度和一个整数被用作同一运算符的操作数时,在计算之前,整数将被静默转换为双精度。结果的类型为 double

所以,你向 printf 传递了一个 double,但是你告诉它期望一个 int,因为你使用了 %d。结果就是一个错误,其结果未定义。

但在 int num = 5.0 + 2; 的情况下,你首先得到一个 double 结果,即 7.0。然后强制将其转换回 int。该代码相当于:

int num = (int)((double)5.0 + (double)2);

更多细节请参见:隐式类型提升规则


3
表达式 5.0 + 2 的结果是 double 类型,因为运算符 + 的两个操作数中至少有一个是浮点数/双精度值(所以另一个将在加法之前转换为 double)。
如果您编写 printf("%d\n", 5.0 + 2),则会将一个浮点值传递到格式说明符实际上期望的 int 中。这种不匹配是未定义行为,您收到的 0 可能是其他数字,崩溃或其他任何东西。
相反,int num = 5.0 + 2 将把从 5.0 + 2 得出的 double 值转换回整数值(丢弃任何小数部分)。因此,num 的值将为 7,并且将与格式说明符 %d 结合使用时有效,因为 num 是整数类型。

1
"5.0+2 is typed double."的英译中:

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); }

编译没有错误并不代表程序正确。
在printf中将"%d"与double匹配会导致未定义的行为。
任何结果都是合法的,包括硬盘被擦除(除非您的程序已经具有这样的功能;如果有,UB可能会导致意外调用)。

0
通常算术转换会隐式地将其值强制转换为公共类型。编译器首先执行整数提升; 如果操作数仍然具有不同的类型,则它们将转换为出现在以下层次结构最高处的类型 -

enter image description here

在这段代码 int num = 5.0 + 2; 中,你正在将一个浮点数与整数相加,并将其存回整数。因此,C会自动将结果强制转换为整数类型变量以存储在其中。因此,在使用 %d 打印时,它可以正常打印。
但是,在这段代码 printf("%d\n", 5.0 + 2); 中,加法被转换为浮点数,因为浮点数的优先级高于整数,但你正在使用 %d 进行打印。这里格式说明符不匹配导致了意外的结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接