C 求值与截断

C 求值与截断,c,truncation,C,Truncation,首先发生什么,截断还是求值?如果我这样做: int a = (2+3)*10.5; int a = 30 / 4 * 5; a得到52,但如果我这样做: int a = (2+3)*10.5; int a = 30 / 4 * 5; a得35分 因此,表达式首先求值,然后被截断。然后将截断的值用于其他计算?”第二条语句中的原因“30/4”首先被计算,然后被截断为7。具体的规则是什么?文档中的任何内容。。。我不是说类型转换,只是在这种情况下截断,就像表达式一个接一个地被截断一样?发生什

首先发生什么,截断还是求值?如果我这样做:

int a = (2+3)*10.5;
int a = 30 / 4 * 5; 
a得到52,但如果我这样做:

int a = (2+3)*10.5;
int a = 30 / 4 * 5; 
a得35分


因此,表达式首先求值,然后被截断。然后将截断的值用于其他计算?”第二条语句中的原因“30/4”首先被计算,然后被截断为7。具体的规则是什么?文档中的任何内容。。。我不是说类型转换,只是在这种情况下截断,就像表达式一个接一个地被截断一样?

发生什么取决于所涉及的值的类型

2
3
30
4
5
都是
int
类型

10.5
具有类型
double

因此,
(2+3)*10.5
执行
2
3
的整数相加,得到
5
(另一个
int
),然后是
5.0
(隐式转换自
5
)和
10.5
,得到
52.5
。此数字被分配给一个
int
,它隐式地将其截断为
52

另一方面,在
30/4*5
中,所有操作数都是
int
s,没有任何操作数转换为
double
。因此,
30/4
执行整数除法,得到
7
,然后乘以
5
,得到
35


没有单独的求值和截断。截断可以作为类型转换的一部分进行,但在
30/4
中,您看到的不是单独的截断和求值步骤,而是单个操作(整数除法)。当然,因为这个结果的类型是
int
,所以它不能有任何小数位。

你问错了问题,没有单独的求值和截断步骤。如果转换后的值不能在目标类型中准确表示,则截断是类型转换的副作用,如

double d = 2.5;
int i = d;       // 2.5 is truncated as a side effect of converting to int
因此,您必须知道在计算表达式时如何转换操作数。确切的规则有点复杂,这里我将重点介绍基本的规则。通常,对于算术运算符,如果操作数尚未具有相同的类型,则其中一个操作数将以某种方式转换,以便两个值都可以表示。在您的第一个示例中:

int a = (2+3)*10.5;
2
3
都是
int
类型,所以它们只是被添加了进去——结果(
5
)又是
int
类型

但是
10.5
具有类型
double
。因此,
5
也被转换为
double
,结果是
52.5
。仅因为将其分配给
int
,它才会转换回
int
,因此必须进行截断

在第二个示例中:

int a = 30 / 4 * 5;
30
4
都具有
int
类型。因此,不进行转换,直接进行分割

这里有一个问题:将两个整数除法是一个整数除法,它再次导致
整数
(这里:
7
)。这不是截断,而是整数除法的定义。事实上,你可能在学校的早期就知道了这个操作,使用了一种叫做。在C中有一个“相反”的模运算(
%
),它将为您提供该除法的剩余部分

因此,这里有类型为
int
的结果
7
,然后乘以
5
,再乘以另一个
int
,因此,同样没有转换——最终结果是
35

检查如果你写了会发生什么

int a = 30.0 / 4 * 5;
相反。现在,
/
的第一个操作数是双精度的,因此
4
也被转换为
double
,结果是
7.5
——这也是
double
,导致
5
转换为
double
,并产生
37.5
的最终结果

这将再次转换为
int
,因为您将其分配给
int
,截断将产生
37


请注意,运算符
/
在这里表示两种不同的含义(实数除法与整数除法),具体取决于其操作数的类型。

不要考虑截断和求值。相反,考虑分组和整数除法。为了进行充分的分析,还需要引入一些其他术语:我已注意将这些术语斜体化

表达式
(2+3)*10.5
因括号而显式分组。所以
5*10.5
是一个中间步骤;这是一种
double
类型,因为
5
int
转换为
double
。此表达式的值为
52.5
,当分配给
int
时,该值被截断为
52

30/4*5
从左到右分组(乘法和除法具有相同的优先级,因此运算符的关联性发挥作用),因此它相当于
(30/4)*5
30/4
7
(整数除法),然后乘以
5
得到结果


一个更有趣的例子是
30/4*5.0
。这仍然是
35
,但属于
double
类型。分组保持为
(30/4)*5.0

使用运算符优先级扣除数据类型。。。。如果
/
*
具有相同的优先级和左关联性,它们将作为
(30/4)*5执行,不是吗<代码>30/4=>7
7*5=>35
。对吗?不进行截断,将两个整数相除,得到一个
int
结果。试试
30.0/4*5
,看看会发生什么。