对于千年虫,学习过计算机基本理论的同学应该都不陌生了,它曾经引起了全世界人民共同关注,并且对当年世界造成了广而深的影响,是计算机历史中的一个大事件。引用互动百科对“千年虫”的解释:

所谓千年虫,泛指由于各种原因,计算机时钟系统不能在1999年以后正确计时,从而导致软件或硬件系统不能正常工作甚至发生崩溃。这里主要是一个两位计年(比如:99年)到四位计年(2000年)转化的问题,由此引发在PC机、收款机、工控机等等计算机控制系统上不可预料的操作故障。

所谓千年虫,其实说白了就是变量溢出问题,当数值超出了当前变量类型所能表示的范围就会发生溢出,下面将会举例说明容易发生变量溢出的一些场合和原因,以及在选择变量类型时需要注意的地方。

在《C陷阱和缺陷》中介绍了C函数库中的fgetc、getc、getchar几个函数的一个缺陷,很多初学者在使用前面提到的几个函数时,都可能会写出下面的代码:

char ch;
while ((ch = fgetc(fp)) != EOF)
{putchar(ch);
}

fgetc等函数返回指是int类型,上面的代码使用char类型存储fgetc的返回值就有可能产生问题了。这里有两点需要注意的:

1) 在32位系统下,int占用4个字节,char占用1个字节
       若将一个int变量赋值给一个char变量,将会导致int变量的前三个字节被截断,因此,ch中存储的数据可能就是错的了;

2) char类型与EOF比较的时候会自动提升为int类型
       当ch与EOF比较的时候会自动提升为int类型,而根据char是unsigned还是signed,当ch被转为int的时候的值不一定相同:

对于上面的例子,若fgetc返回值是0x 00 00 00 FF,而ch的类型为signed char,那么ch就会截断前三个字节,实际保存的值为0x FF,当将ch与EOF比较时,ch会强制转为int类型,其值转为0x FF FF FF FF(即十进制数-1),而系统定义的EOF的值一般都为-1,则此时ch的值就等于EOF的值,循环结束。

(ch = fgetc(fp)) != EOF  //读到值为FF的字符,误认为EOF

这是一个好的数据,并不是文件结尾,却因为溢出而退出了循环。因此,为了得到正确的结果,上面的程序片段中的变量ch应该定义为int类型。

当无符号数赋值给有符号数时,也会发生数据溢出:

unsigned int uValue = 0xffffffff;
int iValue = uValue;cout<<uValue<<endl;    // 4294967295
cout<<iValue<<endl; // -1,已经溢出

有人可能会说,哪有这么笨,有点常识都不会写出以上的代码了,但是要注意的是,当程序的逻辑越来越大以及维护代码的人越来越多的时候,这种情况就有可能出现了,不要小看问题的严重性,往往浪费你几个通宵的debug时间,最后找到的就是你这不以为然的小问题了。

C++之一些事一些情--变量值的溢出问题相关推荐

  1. C++之一些事一些情--写在前面

    记得刚上大学的时候,我第一门学习的编程语言就是C++,从此以后我就对C++情有独钟,其他很多的编程语言使用起来比C++更方便,也有更多的类库支持,但是我就是喜欢C++.说是喜欢,却不代表能学得好,平时 ...

  2. python函数用法详解2(变量的作用域(全局变量、局部变量)、共享全局变量、函数返回值、函数的参数(位置参数、关键字参数、默认参数、不定长参数)、拆包、交换变量值、引用、可变和不可变类型)

    1. 变量作⽤域         变量作⽤域指的是变量⽣效的范围,主要分为两类:局部变量和全局变量. 局部变量         定义在函数体内部的变量,即只在函数体内部⽣效. def testA(): ...

  3. R语言计算回归模型每个样本(观察、observation、sample)的杠杆值(leverage)实战:如果一个样本的预测变量比其他样本的预测变量值更极端,那么被认为具有很高的杠杆作用

    R语言计算回归模型每个样本(观察.observation.sample)的杠杆值(leverage)实战:如果一个样本的预测变量比其他样本的预测变量值更极端,那么被认为具有很高的杠杆作用 目录

  4. Python中变量名与变量值的关系

    在Python中变量名与变量值的只是绑定关系如图,变量名只是一个标识符与变量值绑定在一起而已 转载于:https://www.cnblogs.com/liuxiaowei/p/7163470.html

  5. 同时给两个变量值赋值

    同时给两个变量值赋值 1 --说明:查询"退换货单号","订单编号" 2 --作者:杨斌 3 --日期:2012-09-26 4 Procedure PRO_Q ...

  6. Ubuntu 调试的时候,不能查看变量值

    Ubuntu 快速查看变量值的快捷键和windows不太一样. windows 是 alt + 鼠标左点击. Ubuntu 是 ctrl + alt + shilft + 鼠标左点击 可以在设置里面找 ...

  7. 【C 语言】一级指针 易犯错误 模型 ( 判定指针合法性 | 数组越界 | 不断修改指针变量值 | 函数中将栈内存数组返回 | 函数间接赋值形参操作 | 指针取值与自增操作 )

    文章目录 一.判定指针合法性 二.数组越界 三.不断修改指针变量值 四.函数中将栈内存数组返回 五.函数间接赋值形参操作 六.指针取值与自增操作 一.判定指针合法性 判定指针合法性时 , 必须进行如下 ...

  8. 怎么对jdk核心包进行跟踪调试,并查看调试中的变量值

    java是一门开源的程序设计语言,喜欢研究源码的java开发者总会忍不住debug一下jdk源码.虽然官方的jdk自带了源码包src.zip,然而却存在如下两个问题. a.debug时查看变量十分麻烦 ...

  9. 【Visual Studio】如何在VS 2012中打印变量值到输出窗口

    1.在调试程序时,想要输出某个变量的值到vs的输出窗口,而不是通过添加断点,每次调试时,一步一步的看变量的值,很麻烦,用console.writeline(str);是不行的,这个命令只能用在控制台应 ...

最新文章

  1. MapReduce 计数器简介
  2. Java程序员转Android开发必读经验
  3. VTK:网格之TableBasedClipDataSetWithPolyData2
  4. PostgreSQL 10.1 手册_部分 II. SQL 语言_第 5 章 数据定义_5.5. 修改表
  5. 前端学习(2714):重读vue电商网站34之侧边栏路由改造
  6. 前端 html5 css3 框架,UI,分享,CSS3,HTML5,前端框架
  7. freecplus框架-日期、时间和计时器
  8. python编辑excel文件_python自动化之修改excel(包括xls文件和xlsx文件)
  9. Android 阿里云推送集成指南
  10. Codeforces 1092D1. Great Vova Wall (Version 1)
  11. input onfocus
  12. Prometheus监控docker容器
  13. 【python】cholesky
  14. C语言基础入门48篇_26_身份证号校验程序(以身份证的校验方式是实例加深对数组及函数封装的理解、字符-‘0‘得到字符对应的int类型数字)
  15. 小白普及:云主机与传统服务器的区别
  16. 正则表达式,去除空格标点下划线等
  17. 电子振荡器(Electronic Oscillator)簡介
  18. kvc实践一:核心方法和进阶
  19. 常用的归一化(Normalization) 方法:BN、LN、IN、GN
  20. 电脑PC软件 EXE软件文件加密工具

热门文章

  1. [Swift]LeetCode976. 三角形的最大周长 | Largest Perimeter Triangle
  2. 买天猫网店转让怎么变更资料
  3. 计算机网络 实验三 网络互联与路由协议配置
  4. 艺赛旗(RPA)Python 学习之异常
  5. 星辰小队针对于软件“星遇”的10天冲刺——第7天
  6. 省市区三级行政区数据获取和GeoJson地图下载
  7. `全网最细!! 入门必看Git教程链接:https://gitee.com/all-about-git`
  8. 深信服上网行为管理开启snmp_华为路由器、深信服NGAF防火墙的SNMP配置
  9. SSM 之 MyBatis
  10. Centos7 安装指定版本Gitlab