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值为 65int 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类型
)。
- (2)类型转换
在
(a + b)
中,a被提升为int类型
(实际上它已经是int类型
了,因为char类型
在这里被提升),
然后与 b相加得到 75(int类型
)。
然后,(double)(a + b)
将 75(int类型
)转换为75.0(double类型
)。
- (3) 操作符的应用
最后,
75.0 / c
执行浮点除法运算,
结果是 20.833333(double类型
)。
- (4)优先级和结合性
在这个表达式中,括号()的优先级最高,
所以首先计算(a + b)
。
然后是类型转换(double类型
)(…)。
最后是除法运算/
。
由于除法和类型转换都是从左到右结合的,所以它们的顺序是确定的。
结果:
ret 的值为 20.833333
(具体值可能因编译器和平台而异,但大致接近这个值)。
输出结果:
总结
即使有了操作符的优先级和结合性,我们写出的表达式依然有可能不能通过操作符的属性确定唯一 的 计算路径,
那这个表达式就是 存在潜在风险的,建议 不要写出特别复杂的的表达式。
END
每天都在学习的路上!
On The Way Of Learning