C语言中操作符详解(终结篇)
放在最前面的表达式求值定义(1) 操作数的求值(2) 操作符的应用(3)类型转换(3.1)隐式类型转换(Type Promotion)举例分析:(上代码)输出结果: (3.2)算术转换(Arithmetic Conversion)举例分析:(上代码)输出结果: (4)优先级和结合性举例分析:(上代码)输出结果: 综合举例分析:(上代码)代码详细分析:输出结果: 总结 END
放在最前面的
? ? 我的CSDN主页:OTWOL的主页,欢迎!!!????
??我的C语言初阶合集:C语言初阶合集,希望能帮到你!!!?
? ????创作不易,欢迎大家留言、点赞加收藏!!! ???
表达式求值
定义
C语言中的表达式求值是一个复杂但有序的过程,
它涉及多个步骤和原则,
包括操作数的求值、操作符的应用、类型转换、以及优先级和结合性的考虑。
下面我将详细解释这些方面,并通过例子进行分析。
(1) 操作数的求值
在C语言中,表达式的求值通常 从左到右 进行(除非受到操作符优先级和结合性的影响)。
首先,表达式中的所有操作数都会被求值。
如果操作数是变量或复杂表达式,那么这些变量或表达式的值会被计算出来。
(2) 操作符的应用
一旦操作数被求值,接下来就会根据操作符的类型(如算术操作符、关系操作符、逻辑操作符等)对它们进行相应的运算。
在这个过程中,类型转换(特别是隐式类型转换)可能会发生。
(3)类型转换
类型转换 是 C语言表达式求值中 的一个重要方面。
当两个不同类型的操作数参与运算时,编译器会根据一定的规则将它们转换为一种公共类型。
这些规则通常包括 整数提升、浮点提升 以及 算术转换。
(3.1)隐式类型转换(Type Promotion)
隐式类型转换发生在两个不同类型的操作数参与运算时,
编译器会自动将它们转换为一种公共类型,然后进行运算。
这种转换通常遵循一定的规则,
如 整数提升(Integer Promotion)和 浮点提升(Floating Promotion)。
整数提升:小的整数类型(如char
和short
)会被提升为 int
类型(如果 int
能表示其所有值),如果不能,则提升为 unsigned int
。
浮点提升:float
类型通常会被提升为 double
类型进行运算。
举例分析:(上代码)
#include<stdio.h>int main(){char a = 10;int b = 20;float ret = a + b; // 这里a会被提升为 int,然后与 b相加,结果再转换为 float//输出printf("ret = %f\n", ret);return 0;}
输出结果:
(3.2)算术转换(Arithmetic Conversion)
算术转换 是隐式类型转换的一种特殊情况,发生在涉及算术运算符(如+, -, *, /
)的表达式中。
它的规则比一般的隐式类型转换更为具体:
1. 如果操作数中有long double
类型,则另一个操作数被转换为long double
。
2. 否则,如果操作数中有double
类型,则另一个操作数被转换为double
。
3. 否则,如果操作数中有float
类型,则另一个操作数(如果为整型)被转换为float
(整型提升为int后)。
4. 否则,所有操作数都被转换为int
类型(如果它们原本是char
或short
类型,则先进行整数提升)。
举例分析:(上代码)
int main(){float x = 3.14f;int y = 2;double ret = x * y; // y会被提升为 float,然后与 x相乘,结果再转换为 double//输出printf("ret = %lf\n", ret);return 0;}
输出结果:
(4)优先级和结合性
操作符的 优先级 决定了在表达式中哪个操作首先被执行。具有更高优先级的操作符会先被计算。
如果两个操作符具有相同的优先级,则它们的 结合性 决定了操作是从左到右还是从右到左进行。
优先级:
例如,乘法( *
)和除法( /
)的优先级高于加法( +
)和减法( -
)。
括号( ()
)可以用来改变默认的优先级顺序。
大多数操作符(如加法、乘法、赋值等)是从左到右结合的。
这意味着当操作符 具有相同的优先级时,操作会从左到右 依次进行。
但是, 也有一些操作符(如单目操作符 和 赋值操作符等)是从右到左结合的。
举例分析:(上代码)
#include<stdio.h>int main(){int a = 5, b = 10, c = 20;int ret = a + b * c; // 因为乘法优先级高于加法,所以先计算 b*c,然后加上a//输出printf("ret = %d\n", ret);return 0;}
输出结果:
综合举例分析:(上代码)
#include <stdio.h>int main() { char a = 'A'; // ASCII值为 65 int b = 10; double c = 3.5; double ret = 0.0; // 表达式求值 ret = (double)(a + b) / c; // 打印结果 printf("ret = %lf\n", ret); return 0;}
代码详细分析:
(1)操作数求值:
a 的值是65(char类型
,ASCII值为65
)。
b 的值是10(int类型
)
c 的值是3.5(double类型
)。
在 (a + b)
中,a被提升为 int类型
(实际上它已经是int类型
了,因为char类型
在这里被提升),
然后与 b相加得到 75(int类型
)。
然后,(double)(a + b)
将 75(int类型
)转换为75.0(double类型
)。
最后,75.0 / c
执行浮点除法运算,
结果是 20.833333(double类型
)。
在这个表达式中,括号()的优先级最高,
所以首先计算
(a + b)
。然后是类型转换(
double类型
)(…)。最后是除法运算
/
。由于除法和类型转换都是从左到右结合的,所以它们的顺序是确定的。
结果:
ret 的值为 20.833333
(具体值可能因编译器和平台而异,但大致接近这个值)。 输出结果:
总结
即使有了操作符的优先级和结合性,我们写出的表达式依然有可能不能通过操作符的属性确定唯一 的 计算路径,
那这个表达式就是 存在潜在风险的,建议 不要写出特别复杂的的表达式。
END
每天都在学习的路上!
On The Way Of Learning