-1大于1,-1乘3不等于-3,C语言这个规则你必须得会!
哈喽,大家好。今天我们由C语言的一个经典题目入手,跟大家聊聊C语言一个非常重要的规则,不要着急,让我们从-1大于1的例子说起。
unsigned int i=1;
signed int j=-1;
很简单,无符号数i,有符号数j,比较i和j的大小,按照常理i是大于j的,但是实验证明j>i,也就是说-1>1,为什么会这样呢?
其实出现这个情况的原因就是C语言中的自动转换原则,这也是今天我们想给大家说的话题。在C语言中,若遇到无符号数和有符号数之间的操作,这时候会出现数据类型的提升现象,编译器会自动把有符号数转化为无符号数来进行处理,因此i是1没错,但j却不是-1了,而是变成了 4294967295。所以j>i了。
关于数据为何是4294967295,我们今天从数学的角度给大家分析一下,供大家参考。
首先大家知道无符号数unsigned int的表示范围是:[0 4294967295 ]= [0 2147483647] U [2147483648 4294967295],数学上称为值域。而有符号数int的值域是 [-2147483648—2147483647]。两个区间的元素个数都是4294967296个。
由此看出,二者的公共域是[0 2147483647],所以有符号数int的[-2147483648 -1] 对应 unsigned int的[2147483648 4294967295],这种一一对应的关系,数学上叫做映射。到这里,数据的对应关系就一目了然了, -1 自然对应的就是 4294967295了。
由-1大于1的例子,我们对C语言的自动转换原则进行简单总结。
一般来说,C语言存在4种情况的自动转换,也称为隐式转换。
1、算术运算式中,低级类型转换为高级类型。 (下面的图对低级和高级进行了说明,大家可以参考)
2、赋值表达式中,右边表达式的值自动隐式转换为左边变量的类型,并赋值给他。
3、函数调用中参数传递时,系统隐式地将实参转换为形参的类型后,赋给形参。
4、函数有返回值时,系统将隐式地将返回表达式类型转换为返回值类型,赋值给调用函数。
当然,以上情况只是进行了一般的总结,有些细节还没有提到,比如字符必须先转换为整数,short必须转换为int,float型数据在运算时必须转换为double来提高运算精度等等,有兴趣的可以自行去了解学习。
了解自动转换原则后,我们再来看这个微软面试题
#include<iostream>
using namespace std;
int main(void)
{
unsigned int i=3;
cout<<i * -1;
return 0;
}
问结果会输出什么?有人说不是3而应该是12884901885,因为发生了隐式转换。其实本题的答案是4294967293,哪里有问题呢?我们一步一步分析,有符号数-1与无符号数3进行算数运算,-1变为无符号数4294967295,再乘3得12884901885。到这里都没问题,但是有一点很多人忽略了:那就是无符号数unsigned int只能表示32位,而此时的结果发生了溢出!因此结果是4294967293。
最后,关于本题这里有一点,因为上述代码是C++,大家可以改写成C语言,用printf来输出,再看看运行结果,你会有新的发现哦!好啦,就写到这里吧,希望今天的文章对大家的学习有所帮助。
- Mysql性能优化之开启Mysql慢查询日志
- 三分钟理解“命令模式”——设计模式轻松掌握
- 把表单转成json,并且name为key,value为值
- PHP经典面试题目汇总(上篇)
- 横向滑动的HorizontalListView滑动指定位置的解决方法
- 高可用架构-- MySQL主从复制的配置
- 零基础入门深度学习 | 第二章:线性单元和梯度下降
- 比特币价,黄金和无稽之谈 - 怎样不去给比特币估值
- 在PHP中,cookie和session的使用
- 剑指 offer代码解析——面试题29数组中出线次数超过一半的数字
- 剑指offer代码解析——面试题25二叉树中和为某一值的路径
- Spring MVC 4.2 CORS 跨域访问
- 剑指offer代码解析——面试题31连续子数组的最大和
- 在VS2010上使用C#调用非托管C++生成的DLL文件(图文讲解) 背景
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 单词搜索
- JVM运行时数据区
- 最长重复子数组
- 编辑距离
- 有序矩阵中第K小的元素
- nodejs库yaml读取yml或yaml配置文件
- 爬虫小白:03.requests的使用
- Oracle GoldenGate 19 Microservices数据同步实战与故障处理
- 给“小白”漫画+图示讲解MyBatis原理,就问香不香!
- webClientTest 编写单元测试类
- 关于gorm多表联合查询(left join)的小记
- UnicodeEncodeError: 'latin-1' codec can't encode character 'u2026' in position 30: ordinal not i...
- Oracle GoldenGate 19 Microservices完整高可用安装、配置与测试
- 爬虫小白:11.scrapy框架(六) _媒体管道
- R基于TCGA数据画生存曲线