1. 背景
在嵌入式软件开发中我们对无符号数使用有特别的偏好 -‘遵从能省则省的原则,无符号能表示更大的数字’,这是由于嵌入式开发相对于其它资源仍然较为紧缺,不可避免会使用无符号数的减法,当”a-b;a<b”无论是过程还是结果你都可能不存在疑问而且这个结果也能被很好的理解;但当”a-b;a<b”无论是结果还是过程可能存在一些疑惑,例如“a、b都为无符号数,但这个结果是有符号还是无符号?”。a-b仍较为抽象,下面以一个更加实际的遇到的问题进行展开:
为了解决“t2-t1且t2<t1”这种特殊情况,你是否是使用以下代码:
uintx_t dt=0;
if(t2<t1)
{
dt = 0xffff-t2+t1 ; //这里假定计数器的最大值为0xffff
}
else
{
dt = t2-t1 ;
}
uintx_t dt = t2-t1 ;//uintx_t 表示与t1/t2同类型
#include "stdio.h"
#include "stdint.h"
int main()
{
{
uint8_t t1 = 0xff-1 ,t2 = 1;
printf("uint8:%u-%u=%urn",t2,t1,t2-t1);
}
{
uint16_t t1 = 0xffff-1 ,t2 = 1;
printf("uint16:%u-%u=%urn",t2,t1,t2-t1);
}
{
uint32_t t1 = 0xffffffff-1 ,t2 = 1;
printf("uint32:%u-%u=%urn",t2,t1,t2-t1);
}
#include "stdio.h"
#include "stdint.h"
int main()
{
{
uint8_t t1 = 0xff-1 ,t2 = 1;
printf("uint8:%u-%u=%drn",t2,t1,t2-t1);
}
{
uint16_t t1 = 0xffff-1 ,t2 = 1;
printf("uint16:%u-%u=%drn",t2,t1,t2-t1);
}
{
uint32_t t1 = 0xffffffff-1 ,t2 = 1;
printf("uint32:%u-%u=%drn",t2,t1,t2-t1);
}
}
#include "stdio.h"
#include "stdint.h"
int main()
{
{
uint8_t t1 = 0xff-1 ,t2 = 1;
printf("uint8:%u-%u=%urn",t2,t1,(uint8_t)(t2-t1));
}
{
uint16_t t1 = 0xffff-1 ,t2 = 1;
printf("uint16:%u-%u=%urn",t2,t1,(uint16_t)(t2-t1));
}
{
uint32_t t1 = 0xffffffff-1 ,t2 = 1;
printf("uint32:%u-%u=%urn",t2,t1,(uint32_t)t2-t1);
}
}
2. 无符号数减法原理
虽然我们经常使用了无符号数进行减法运算,但其实无符号数不能直接进行减法运算,无符号数进行减法运算前会将其转换成有符号数进行运算,以下为一段验证在PC上测试源码:
#include "stdio.h"
#include "stdint.h"
int main()
{
uint8_t a = 1;
uint16_t b = 1;
uint32_t c = 1;
printf("sizeof(uint8):%u sizeof(-uint8)=%urn",sizeof(a),sizeof(-a));
printf("sizeof(uint16):%u sizeof(-uint16)=%urn",sizeof(b),sizeof(-b));
printf("sizeof(uint32):%u sizeof(-uint32)=%urn",sizeof(c),sizeof(-c));
}
3.测试2中uint32无符号减法为什么没有产生负数结果
通过上面原理分析我们已经知道,在计算过程中会优先转成成有符号int32类型(有符号),但测试2的uint32数据已经超出了int32类型所能超过范围,这样导致-t1其实已经变成了一个正数,结果变成了两个正数相加,所以这种情况下没有产生负数,对结果的没有进行值域限制结果仍然是正常的。
#include "stdio.h"
#include "stdint.h"
int main()
{
{
uint8_t t1 = 0xff-1 ,t2 = 1;
printf("uint8:%u-%u=%drn",t2,t1,t2-t1);
}
{
uint16_t t1 = 0xffff-1 ,t2 = 1;
printf("uint16:%u-%u=%drn",t2,t1,t2-t1);
}
{
uint32_t t1 = 0xffffffff-1 ,t2 = 1;
printf("uint32:%u-%u=%drn",t2,t1,t2-t1);
}
}
测试2运行结果:
原创文章,作者:guozi,如若转载,请注明出处:https://www.sudun.com/ask/88932.html