服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++无符号整数溢出问题解析

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

2022-12-20 16:55李迟 C/C++

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

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

问题提出

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

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

设计思路

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

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

工程代码

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 测试无符号溢出后的差值 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++;
    }
}

测试代码:

?
1
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时,测试结果如下:

?
1
2
3
4
5
6
7
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时,测试结果如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
第一次测试:
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++无符号整数溢出内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/7106302326763159565

延伸 · 阅读

精彩推荐
  • C/C++C++中约数定理的实例详解

    C++中约数定理的实例详解

    这篇文章主要介绍了C++中约数定理的实例详解的相关资料,需要的朋友可以参考下...

    ruangongshi10692021-05-23
  • C/C++C语言学生信息管理系统

    C语言学生信息管理系统

    这篇文章主要为大家详细介绍了C语言学生信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    Combatting9252021-10-15
  • C/C++浅析C++内存布局

    浅析C++内存布局

    本文给大家介绍了C++内存布局的相关知识,通过进程间通信比线程间通信难也是因为进程间的用户空间是相互隔离的,无法相互访问,需要通过进程间通信...

    ~怎么回事啊~7852022-01-21
  • C/C++c++ 形状类Shape(派生出圆类Circle和矩形类Rectangle)

    c++ 形状类Shape(派生出圆类Circle和矩形类Rectangle)

    通过C++方式,建立一个形状类Shape作为基类,派生出圆类Circle和矩形类Rectangle 求出面积并获取相关信息...

    DB伟5732021-10-08
  • C/C++C语言编程PAT乙级学习笔记示例分享

    C语言编程PAT乙级学习笔记示例分享

    这篇文章主要为大家介绍了C语言编程PAT乙级学习笔记实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪...

    今年的浙江省状元6312022-12-07
  • C/C++贪吃蛇C语言代码实现(难度可选)

    贪吃蛇C语言代码实现(难度可选)

    这篇文章主要为大家详细介绍了贪吃蛇C语言代码实现,游戏难度可供选择,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参...

    小-立子11232021-06-19
  • C/C++C++ STL 四种智能指针的用法详解

    C++ STL 四种智能指针的用法详解

    C++ 标准模板库 STL(Standard Template Library) 一共给我们提供了四种智能指针:auto_ptr、unique_ptr、shared_ptr 和 weak_ptr,今天给大家详细介绍这几种指针的具体用...

    青年夏日10642021-11-19
  • C/C++C++数字三角形问题与dp算法

    C++数字三角形问题与dp算法

    这篇文章主要介绍了C++数字三角形问题与dp算法的相关知识,非常不错,具有一定的参考借鉴价值 ,需要的朋友可以参考下...

    会武术之白猫6572021-07-01