数据越界的巧妙利用,负数在计算机的存储方式

问题来源及应对

FPGA模块进行高速信号处理,每隔固定的时间输出一组数据,但由于FPGA没有系统时间及时间戳的概念,在通信协议中用两字节长度记录数据的流水号,每输出一包数据,就在流水号上加一。上位机接收数据并依据流水号打上时间戳。
两字节的流水号用unsigned short类型接收,范围就是0~65535,65535的后一包为65536,溢出后结果为0,就是65535序号的下一包序号为0。
为了打上时间戳,需要知道当前包序号与上一包序号的差值,用插值乘以时间间隔,就得到了这两个报文的时间延迟(不考虑经过了多个轮回)。测试发现如果用unsigned short去存储这个差值的话,就不用考虑溢出的情况,因为0减去65535的结果就是1,1减去65535的结果就是2!

原码反码补码

上面的结果是显而易见的,前提是清楚数据在计算机中的存储方式的话。弄清计算机的存储数据方式的前提是几个概念:
1)原码:十进制转成二进制数就是原码。正数的原码是本身;负数的原码需要将符号为置1。(unsigned类型的数据没有符号位)。
2)反码:正数的反码是原码本身;负数的反码是除了符号位,其它位按位取反,符号位置1(因为正数的符号位是0,故相当于无论是不是符号位,统统按位取反即可)。
3)补码:正数的补码是原码本身,负数的补码是负数的反码加上1。
计算机中存储的数据是补码的形式,参与计算的也是补码的形式。引入补码概念的目的就是方便计算机进行负数的计算,因为无论对正数还是负数而言,补码进行计算后,还是所求结果的补码。

应对方法的支持

unsigned short类型的长度是两字节,即16bit,可以标识的范围是0~65535。
65535的原码为1111 1111(unsigned没有符号位),在计算机中的表示为补码,也为1111 1111。
0-65535,即-65535,short类型越界,计算机默认用int类型存储,-65535的补码,也即计算机的存储形式为1111 1111 0000 0001,用unsigned short类型截短,就是0000 0001,也就是1了。枚举其它的值也是适应的。
具体从数据公式上如何推导就不研究了。

发布了47 篇原创文章 · 获赞 45 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/lusanshui/article/details/86626576