C语言操作符终极揭秘:表达式求值秘籍

放在最前面的

🎈 🎈 我的优快云主页:OTWOL的主页,欢迎!!!👋🏼👋🏼
🎉🎉我的C语言初阶合集C语言初阶合集,希望能帮到你!!!😍
😍 👋🏼🎉🎊创作不易,欢迎大家留言、点赞加收藏!!! 🥳😁😍

表达式求值

定义

C语言中的表达式求值是一个复杂但有序的过程,
它涉及多个步骤和原则,
包括操作数的求值、操作符的应用、类型转换、以及优先级和结合性的考虑。
下面我将详细解释这些方面,并通过例子进行分析。

(1) 操作数的求值

在C语言中,表达式的求值通常 从左到右 进行(除非受到操作符优先级和结合性的影响)。
首先,表达式中的所有操作数都会被求值。
如果操作数是变量或复杂表达式,那么这些变量或表达式的值会被计算出来。

(2) 操作符的应用

一旦操作数被求值,接下来就会根据操作符的类型(如算术操作符、关系操作符、逻辑操作符等)对它们进行相应的运算。
在这个过程中,类型转换(特别是隐式类型转换)可能会发生。

(3)类型转换

类型转换 是 C语言表达式求值中 的一个重要方面。
当两个不同类型的操作数参与运算时,编译器会根据一定的规则将它们转换为一种公共类型。
这些规则通常包括 整数提升、浮点提升 以及 算术转换。

(3.1)隐式类型转换(Type Promotion)

隐式类型转换发生在两个不同类型的操作数参与运算时,
编译器会自动将它们转换为一种公共类型,然后进行运算。
这种转换通常遵循一定的规则,
整数提升(Integer Promotion)和 浮点提升(Floating Promotion)。

整数提升:小的整数类型(如charshort)会被提升为 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类型(如果它们原本是charshort类型,则先进行整数提升)。

举例分析:(上代码)
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类型)。

  • (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

评论 72
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OTWOL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值