当前位置: 首页 > news >正文

c语言-表达式求值

目录

  • 前言
  • 一、隐式类型转换
    • 1.1 整型提升
  • 二、算术转换
  • 三、操作符的属性
  • 四、问题表达式
  • 总结


前言

表达式求值的顺序一部分由操作符的优先级和结合性决定。
有些表达式的操作数在求值的过程中可能需要转换为其他类型


一、隐式类型转换

隐式类型转换是在编译器自动进行的类型转换,无需显式地指定转换操作。
常见的隐式类型转换情况:

  • 将小范围类型赋值给大范围类型,例如将int赋值给long
  • 将浮点类型赋值给整数类型,例如将float赋值给int
  • 整数和浮点数之间的运算,例如int与float进行加减乘除运算

1.1 整型提升

c语言的整型算术运算总是以缺省整型类型的进度来进行的。
为了保证计算的精度,表达式的字符和短整型操作数在使用之前被转换成普通整型,这个过程称为整型提升。
整型提升的原因:

表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。
当两个char类型的值相加,在CPU执行时实际要先转换为CPU内整型操作数的标准长度。
通用CPU是难以直接实现两个8比特位直接相加运算。所以,表达式各种长度可能小于int长度的整型值,都必须转换为int或unsigned int ,然后才 能送入CPU去执行。

分析下面的运算结果:

char a = 5;
char b = 126;
char c = a + b;
printf("%d",c);

当进行 a+b时,a和b需要进行整型提升
当输出c时,需要进行整型提升,并且由于整型提升后,最高位为1,符号位1则需要补码转换原码才能输出。
在这里插入图片描述

图1.1 整型提升过程图

二、算术转换

如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作无法进行。下面的层次体系称为寻常算术转换。

long double
double
float
unsigned long int
long int
unsigned int
int

如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另一个操作数的类型后执行运算。
具体例子如下,如图1.2所示
在这里插入图片描述

图1.2 算术转换代码

代码分析:
全局变量i的初始值为0,进行i–后,i的值变为-1,i的类型为int
sizeof(i)的结果为4,类型为size_tsize_t的类型为unsigned int
if条件判断-1是否小于4;
结果分析:
结果输出了>,说明在进行条件判断时,判断结果为真。(-1 > 4)这个表达式为何为真?
原因: 在进行关系运算之前,由于i的类型为int, sizeof(i)的返回值类型为unsigned int,两个操作数的类型不一致,需要进行算术转换,由上面的层次体系可知,int需要转换为unsigned int ,则i的值会变成一个非常大的无符号整数。
算术转换的过程如图1.3所示:
在这里插入图片描述

图1.2 算术转换过程

三、操作符的属性

复杂表达式的求值有三个影响的因素:

  1. 操作符的优先级
  2. 操作符的结合性
  3. 是否控制求值顺序

两个相邻的操作符先执行哪个,取决于他们的优先级。
如果两者的优先级相同,则取决于他们的结合性。

四、问题表达式

如果不能根据操作符的属性确定唯一的计算路径,那这个表达式就是存在问题的。
下面是问题表达式的例子:

  1. 表达式一
c + --c
  1. 表达式二
int main()
{
int i = 0;
i = i-- - --i * (i= -3) * i++ + ++i;
printf("%d",i);
return 0;
}
  1. 表达式 三
int main()
{
int a = 1;
int b = (++a)+(++a)+(++a);
printf("%d",b);
return 0;
}
  1. 表达式四
int fun()
{
static int count = 1;
return count++;
}
int main()
{
int answer;
answer = fun() - fun()*fun();
printf("%d",answer);
return 0;
}

总结

本篇文章介绍了c语言中的表达式求值。包括隐式类型转换,算术转换和操作符的属性。

http://www.lryc.cn/news/267318.html

相关文章:

  • 小型洗衣机哪个牌子质量好?口碑最好的四款小型洗衣机推荐
  • springCould中的Ribbon-从小白开始【5】
  • 持续集成交付CICD:Jira 发布流水线
  • JuiceSSH结合内网穿透实现公网远程访问本地Linux虚拟机
  • 使用 pytest.ini 文件控制输出 log 日志
  • 【Spring】SpringBoot 配置文件
  • Koordinator 支持 K8s 与 YARN 混部,小红书在离线混部实践分享
  • 网游逆向分析与插件开发-游戏反调试功能的实现-项目需求与需求拆解
  • 阶段七-GitEE
  • Redis小记(1)
  • Flutter windows 环境配置
  • odoo17核心概念view5——ir_ui_view.py
  • 截断整型提升算数转换
  • 阿里云 ECS Docker、Docker Compose安装
  • LeetCode——1276. 不浪费原料的汉堡制作方案
  • 隆道吴树贵:生成式人工智能在招标采购中的应用
  • docker搭建kali及安装oneforall
  • 【MySQL】数据库之事务
  • AGV|RGV小车RFID传感器CNS-RFID-01/1S的RS232通讯联机方法
  • 【Python可视化系列】一文教会你绘制美观的热力图(理论+源码)
  • 百度Apollo五步入门自动驾驶:Dreamview与离线数据包分析(文末赠送apollo周边)
  • 为什么IPv6 可以作为低功耗蓝牙的物联网体系结构?
  • GPT每预测一个token就要调用一次模型
  • 运维工程师的出路到底在哪里?
  • 2312clang,基于访问者的前端动作
  • 怎么搭建实时渲染云传输服务器
  • 如何在生产环境正确使用Redis
  • LeetCode-环形链表问题
  • C# 读取Word表格到DataSet
  • 构建外卖系统:从技术到实战