单片机程序中隐藏的数据溢出陷阱
通常的规则: 当代码中对char、short等更短的类型进行算术运算时,编译器会自动将它们提升为int再进行计算。
假设16位、32位无符号数类 型,分别定义为UINT16、UNIT32
一.计算过程溢出
对16bit单片机,如以下程序
UINT16 a, b, c;
c = (a * b)/10;
故障描述:当a=6554,b = 10,但c出错,(6554*10)/10 != 6554;
原因分析:a * b = 65540,按unsigned int为16bit计算已溢出;
解决方案:c = ((UNIT32)a * b)/10; //手动提升a到32bit
二.移植后溢出
1. 16位单片机,正常运行
设计如下程序, 在主循环中运行10次,处理某件事1次
UINT16 a=0, a0=0;
a++;//记录运行次数,a达到0xffff后+1溢出为0
if((a-a0) >= 10)
{
a0 = a;//记录当前时刻
//处理其它逻辑
}
当a0=65530,a=4(a当前65530,经过10次运行,变成4,)时处理事情
在程序中,UINT16就是本机字长,直接处理不提升,那么a-a0 = 4-65530 = −65526 = 10(在无符号整数运算中,结果的溢出遵循模2的16次方回绕规则)
2. 移植到32位单片机,不能正常运行
故障描述:在a++溢出返回0后,程序异常;
原因分析:(a-a0)提升为32位有符号数int,−65526在范围内不会转换,-65526 >= 10不成立;
解决方案:if((UNIT16)(a-a0) >= 10)
————————————————
版权声明:本文为CSDN博主「汽车芯猿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dangpu/article/details/158740122
|
评论
|