为什么会发生这种情况?这只是C语言的东西吗?
我正在学习cs50课程。
#include <stdio.h>
int main(void)
{
int testInt = 5;
printf("%f", testInt / 4.0);
}
输出为1.250000--浮动值
在计算表达式时,编译器需要确定表达式的常用操作数类型。
所以对于这个表达式
testInt / 4.0
(其中4.0
是double
类型的浮动常数)由于double
类型的对象的值的范围大于int
类型的对象值的范围,则编译器将int
类型的对象转换为double
类型的对象(因为至少由于类型double
的对象的截断,进行这种转换而不是将类型double
的对象转换为类型int
的对象是更安全的)并且执行操作。
这种转换被称为通常的算术转换,并在C标准中进行了描述。
来自C标准(6.3.1.8常用算术转换)
否则,如果任一操作数的对应实数类型为双,另一个操作数被转换为类型,其对应的实类型为double。
这只是C语言的东西吗?
答案是"因为C语言就是这样定义操作的">
在许多语言中,在使用另一个浮点值执行操作之前,将整数提升为浮点是很常见的。
如果它不以这种方式工作,就会出现许多意外的精度损失(或信息丢失)错误。
为什么用浮点值除int会产生浮点值?
在C中,使用像*, / +, -, %
这样的运算符,当两个操作数的类型不同时,通过将排名较低的操作数转换为较高的操作数,可以找到一个通用的操作数。
int
的级别低于float
,因此转换了int
操作数。
语言可以以不同的方式指定int * float
——可能是某种some_type mult_int_by_float(int, float)
操作。然而,这种方法导致了许多组合,并且仍然没有给出结果的类型。提升排名较低的类型更简单。
一种具有N种类型的语言可以进行N*N种不同的乘法运算。使用C的排序和转换方法,它更像是N个不同的乘法运算。
这只是C语言的东西吗?
是。TL/DR;版本是将具有较窄/较不精确类型的操作数转换为与具有较宽/更精确类型的操作数相同的类型,并且结果的类型与具有较广/更精确的类型的操作数数的类型相同。以下是一组特定的规则:
6.3.1.8常用算术转换
- 许多期望算术类型操作数的运算符会导致转换并产生结果类型。其目的是为操作数确定公共实数类型以及结果。对于指定的操作数,在不更改类型的情况下转换每个操作数域,转换为其对应的实数类型为公共实数类型的类型。除非明确指出,否则,公共实数类型也是的对应实数类型如果操作数相同则其类型域是操作数的类型域的结果,而在其他方面则很复杂。这种模式被称为常用算术转换:
- 首先,如果任一操作数的对应实数类型为
long double
,则另一个操作数在不更改类型域的情况下转换为相应实类型为long double
的类型。- 否则,如果任一操作数的对应实数类型为
double
,则另一个操作数在不更改类型域的情况下转换为其类型对应的实型为double
。- 否则,如果任一操作数的对应实数类型为
float
,则另一个操作数在不更改类型域的情况下转换为其类型相应的实型为float
。62)- 否则,对两个操作数执行整数提升。然后以下规则应用于提升的操作数:
- 如果两个操作数的类型相同,则不需要进一步转换。
- 否则,如果两个操作数都具有带符号整数类型或都具有无符号整数类型整数类型,具有较小整数转换秩类型的操作数为转换为具有更大秩的操作数的类型。否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的秩,然后是具有带符号整数类型转换为带无符号的操作数的类型整数类型。
- 否则,如果带符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数的类型的所有值,然后无符号整数类型的操作数转换为带符号整数类型的操作数。
- 否则,两个操作数都转换为无符号整数类型对应于具有带符号整数类型的操作数的类型
62)例如,添加一个double _Complex
和一个float
只需要转换float
操作数转换为double
(并生成double _Complex
结果)
C 2011在线草案
如果两个操作数都是整数,则结果为整数。如果任一操作数是浮点类型,则结果为浮点类型。