| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> C语言:表达式求值(整型提升、算术转换 ...) -> 正文阅读 |
|
[C++知识库]C语言:表达式求值(整型提升、算术转换 ...) |
表达式求值表达式求值的顺序,一部分是由操作符的优先级和结合性决定的。 同样,有些表达式的操作数在求值的过程中可能需要转换成其它类型。 表达式求值,先看有没有隐式类型转换(整型提升/算数转换),然后再看操作符的优先级和结合性 1)整型提升(隐式类型转换)先来看一段程序:
相信很多初学者看到此段代码,都会以为程序会输出 130 ,但其实运行发现,正确结果是 -126 为什么呢?这就涉及到下面要讲的隐式类型转换中的整型提升了 C语言的整型算术运算总是至少以缺省整型类型的精度来进行的。为了获得这个精度,表达式中的字符 char 和短整型 short 操作数在使用之前被转换成普通整型 int ,这种类型转换称为整型提升。 int 类型是最适应计算机系统架构的整数类型,它具有和 CPU 寄存器相对应的空间大小和位格式。
在运算中,char 类型和 short 类型都没有达到一个 int 类型的大小,但 CPU 又是以整型 int 的方式来计算的,如果我们能够把长度小于 int 的提升成 int 来计算,这样计算的精度就提高了。
实例:
1、如何进行整型提升
负数 -128 在 char 类型的取值范围内,其在内存中的补码形式:
变量 a 是一个有符号数,最高位为 1 表示负数,所以整型提升的时候,高位补充符号位,即为 1 整型提升之后的结果为:
正数 1 在 char 类型的取值范围内,其在内存中补码形式:
因为变量 a 是一个有符号数,最高位为 0 表示正数,所以整型提升的时候,高位补充符号位,即为 0 整型提升之后的结果为:
正数 300 超过了 char 类型的取值范围,其在内存中的补码形式:
变量 a 是无符号类型,表示一个正数 而 char 类型占用一个字节,所以 300 存入变量 a 截断保留低8位的二进制数,其余部分抛弃,得到变量 a 的二进制序列(补码)如下:
无符号数整型提升时高位补 0 ,结果为:
将补码转换为原码就是十进制的 44 2、整型提升的例子实例1:
运行结果:
实例2:
运行结果为:
运行结果分析,两种理解的角度:
实例3:
第4个输出语句,VS中可能会输出 1 ,我们以 gcc 编译器为准,更加符合C语言的标准,VS编译器有时候在实现的时候没有尊重C语言的标准 运行结果分析:
比如:
运行结果:
3、一些补充:char取值范围要注意C语言中赋值时超出范围的数据的计算方法 对 char 类型变量赋值最容易超出范围,记得要截断保留低8位哦 signed char 整数取值范围: -128~127【 1000 0000(-128) ~ 0111 1111(127)】 unsigned char 整数取值范围:0~255【 0000 0000(0) ~ 1111 1111(255)】
例:
所以: 无论你往 signed char 类型变量里放多大的数字,因为 char 只能存8个比特位,所以变量中截断保留的数值范围始终在-128~127之间 无论你往 unsigned char 类型变量里放多大的数字,因为 char 只能存8个比特位,所以变量中截断保留的数值范围始终在0~255之间 2)算术转换(隐式类型转换)某个操作符的各个操作数属于不同类型,那么除非其中一个操作数转换成另一个操作数的类型,否则操作无法进行。下面的层次体系称为寻常算数转换。
如果某个操作数的类型在上面列表中排名较低,首先要转换成另外一个排名高的操作数的类型后,再执行运算。 从列表下到上转换,即字节短的操作数向字节长的转换,字节长度相同,精度低的向精度更高的转换。
3)操作符属性观察下面这个表达式
复杂表达式的求值有三个影响因素:
两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。 1、操作符的优先级推荐文章:C语言运算符优先级和结合性一览表 这里重点讲解一下需要注意的一些操作符 rexp:表达式 L-R:从左到右
逻辑与,当左边表达式为假,右边是真还是假不重要了,因为它整体就为假了,所以右边表达式就不会运算了 所以它会控制求值顺序,让某一个部分会运算,而让某一部分不会去运算了。 条件操作符,表达式1成立,表达式2计算,而表达式3就不会计算了。 逗号操作符,整个表达式从左到右都会依次计算,但真正起到作用的,是最后一个表达式。 2、一些问题表达式学习完上面的表达式求值顺序后,是不是只要写出一个表达式,我们就能求出它的值呢?来看下面的例子 代码1:
它的求值顺序是哪一种呢,这个? 还是这个? 好像两种都没有问题,都有理由说得通,但没有办法确定唯一的计算路径 所以,在写代码的过程中,一定要避免写出这种有歧义的代码,可以把它拆分写成三个语句,然后再相加,这样计算顺序就是可控的 代码2:
注意:
代码3:
函数的调用顺序到底是哪一种呢?
代码4:
VS编译环境中,先依次计算三个 开启调试,打开调试 - 窗口 - 反汇编,查看汇编代码,执行过程一目了然 Linux环境 gcc 编译器,先依次计算第一个和第二个 总结: 我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题的。 |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 21:02:07- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |