C++无符号整数溢出问题解析

 更新时间:2022年06月08日 10:55:10   作者:李迟  
这篇文章主要介绍了C++无符号整数溢出探究,本文主要探讨C/C++中无符号整数超过范围后的计算问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

本文主要探讨C/C++中无符号整数超过范围后的计算问题。

问题提出

nrf52832 的 SDK 中是没有时间戳获取的函数的,为了统计性能耗时,也为了向一些库提供时间戳(毫秒级别),需要自己利用定时器实现获取毫秒的接口。

nrf52832 是 32 位的,按毫秒计算,大概49天就会达到最大值,如何处理毫秒数值溢出后的情况,其实我是不懂的。看了些帖子,说在单独处理溢出反转的情形,但总觉得这样不太好,因此集中了一点时间,了解学习了无符号数的溢出(或说进位),并写了点代码测试。

设计思路

为了方便调试,本文用 32 位虚拟机 Linux 进行测试。用get_time获取系统的秒数值,其值用g_ms表示,开一线程time_handler每秒累计一次时间数值,开另一线程myfunc_sleep统计耗时。

需要注意的是,上面所述仅是模拟演示,旨在说明本质问题,并非实际使用的。

工程代码

首先简单测试无符号数的相加,函数如下:

// 测试无符号溢出后的差值 delta
void delta_test(int delta)
{
    mytime_t start = 0xfffffffe;
    /* 以ms为10为例,ent得到的结果为8
     8 - start = 10
     因此,即使溢出后,差值也是不变的
     在延时函数中,即使时间戳溢出,也是无问题的。
     */
    mytime_t end = start + delta;
    
    mytime_t mydelta = end - start;
​
    printf("end: %u start: %u delta: %u mydelta: %u\n", end, start, delta, mydelta);
    for (int i = 0; i < delta; i++)
    {
        printf("%u %d\n", start, start);
        start++;
    }
}

测试代码:

delta_test(10);

其打印结果如下:

end: 8 start: 4294967294 delta: 10 mydelta: 10
4294967294 -2
4294967295 -1
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7

起始数值为0xfffffffe,即4294967294,使用有符号打印,其值为-2。当超过0xffffffff则从0开始计数。如果仅从结果看,可得到:8 - 4294967294 = 10,与传递的参数一致。

下面给出多线程测试代码:

代码中定义的时间戳变量为mytime_t,实际上是无符号类型unsigned。另外也做了测试,在32位机器上使用uint8_t类型也可以得到正确值,但负数就无法打印出来了。

测试

g_start的值为0xfffffffe时,测试结果如下:

test of unsigned overflow..
sizeof: 4
after sleep 3 s  1 - 4294967294 = 3
after sleep 3 s  4 - 1 = 3
after sleep 3 s  7 - 4 = 3
after sleep 3 s  10 - 7 = 3
after sleep 3 s  13 - 10 = 3

g_start的值为0xfffffff0时,测试结果如下:

第一次测试:
test of unsigned overflow..
sizeof: 4
after sleep 2 s  4294967282 - 4294967281 = 1
after sleep 2 s  4294967284 - 4294967282 = 2
after sleep 2 s  4294967286 - 4294967284 = 2
after sleep 2 s  4294967288 - 4294967286 = 2
after sleep 2 s  4294967290 - 4294967288 = 2
after sleep 2 s  4294967292 - 4294967290 = 2
after sleep 2 s  4294967294 - 4294967292 = 2
after sleep 2 s  0 - 4294967294 = 2
after sleep 2 s  2 - 0 = 2
after sleep 2 s  4 - 2 = 2
after sleep 2 s  6 - 4 = 2
after sleep 2 s  8 - 6 = 2
​
第二次测试:
test of unsigned overflow..
sizeof: 4
after sleep 2 s  4294967282 - 4294967280 = 2
after sleep 2 s  4294967284 - 4294967282 = 2
after sleep 2 s  4294967286 - 4294967284 = 2
after sleep 2 s  4294967288 - 4294967286 = 2
after sleep 2 s  4294967290 - 4294967288 = 2
after sleep 2 s  4294967292 - 4294967290 = 2
after sleep 2 s  4294967294 - 4294967292 = 2
after sleep 2 s  0 - 4294967294 = 2
after sleep 2 s  2 - 0 = 2
after sleep 2 s  4 - 2 = 2
after sleep 2 s  6 - 4 = 2
after sleep 2 s  8 - 6 = 2

从结果上看,基本符合要求,即延时2秒,统计的耗时是2。——不管是否有溢出。

扩展知识

计算机中数值存储的是2的补码(2’s complement)。正数的补码是其本身,负数的补码是原码基础上取反码,末位加1。

mpu6050 芯片的陀螺仪和加速度数值,是16位有符号数值,就是用2的补码形式存储的。

小结

对于计时、延时类的函数,记录时间戳的变量为无符号数。类型为unsinged,不能加范围限制,这是指平台最大者,如32位系统,使用的是32位无符号数,64位的系统则是64位无符号数。当变量数值溢出后,其值归0,但计时函数是正常的,不需要额外处理溢出情况。

到此这篇关于C++无符号整数溢出探究的文章就介绍到这了,更多相关C++无符号整数溢出内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • C++概念重载、覆盖、隐藏的使用说明

    C++概念重载、覆盖、隐藏的使用说明

    本篇文章介绍了,在C++中概念重载、覆盖、隐藏的使用分析说明。需要的朋友参考下
    2013-05-05
  • 如何使用递归和非递归方式反转单向链表

    如何使用递归和非递归方式反转单向链表

    以下是对使用递归和非递归方式反转单向链表的示例进行了详细的分析介绍,需要的朋友可以过来参考下
    2013-07-07
  • C++二维数组螺旋加密信息

    C++二维数组螺旋加密信息

    大家好,本篇文章主要讲的是C++二维数组螺旋加密信息,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • C++读取单个字符操作示例详解

    C++读取单个字符操作示例详解

    这篇文章主要为大家介绍了C++读取单个字符操作示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • C语言指针必备基础全面覆盖

    C语言指针必备基础全面覆盖

    数据对象是指存储在内存中的一个指定数据类型的数值或字符串,它们都有一个自己的地址,指针是保存这个地址的变量,本篇文章带你掌握C语言指针的用法
    2021-10-10
  • 关于C++动态分配内存的介绍

    关于C++动态分配内存的介绍

    今天小编就为大家分享一篇关于关于C++动态分配内存的介绍,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • 基于Matlab实现BP神经网络交通标志识别

    基于Matlab实现BP神经网络交通标志识别

    道路交通标志用以禁止、警告、指示和限制道路使用者有秩序地使用道路, 保障出行安全.若能自动识别道路交通标志, 则将极大减少道路交通事故的发生。本文将介绍基于Matlab实现BP神经网络交通标志识别,感兴趣的可以学习一下
    2022-01-01
  • C数据结构循环链表实现约瑟夫环

    C数据结构循环链表实现约瑟夫环

    这篇文章主要介绍了C数据结构循环链表实现约瑟夫环的相关资料,需要的朋友可以参考下
    2017-05-05
  • C语言进阶之内存操作函数详解

    C语言进阶之内存操作函数详解

    这篇文章主要为大家学习介绍了C语言中内存操作函数(memcpy、memmove和memcmp)的使用,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2023-07-07
  • 利用Matlab实现时域分析功能的示例详解

    利用Matlab实现时域分析功能的示例详解

    利用MATLAB可以方便地进行控制系统的时域分析。这篇文章主要通过简单的示例为大家介绍了Matlab进行时域分析的具体操作,需要的可以参考一下
    2023-02-02

最新评论