关于32位计数器溢出问题
原创
©著作权归作者所有:来自51CTO博客作者luteresa的原创作品,请联系作者获取转载授权,否则将追究法律责任
好久没写博客了,昨天遇到一个时间计数溢出问题, 做个简单记录吧
unsigned int的变量表示自开机以来累计时间,用作码流的时间戳,单位ms.
32位无符号数的毫秒计数,大概49天就会溢出,溢出后时间计数用作时间戳就会出错,导致无法正确解码。
64位变量来保存累计时间,
方法如下:
此处)折叠或打开
unsigned long long ullCurFrmPts=0;//app里用到的时间戳,微秒计
int bf_stamp=0;
int timestamp=0;//SDK提供的时间戳
= ullCurFrmPts&0xffffffff);
if(timestamp*1000 < bf_stamp) {
= (ullCurFrmPts + 1<<32);
}
= (ullCurFrmPts&0xffffffff00000000)+timestamp*1000;
运行,时间怎么都不对
1:
32位ARM上实现的unsigned long long是否64位?
测试代码
此处)折叠或打开
int num=0;
=0;
test = ~0;
("test is %llx\n",test);
num=0;
while(1){
if(test&0x1){
++;
}
= test>>1;
if (test == 0)break;
("test is %llx\n",test);
}
("test is %dbit\n",num);
执行结果如下
此处)折叠或打开
[root@GM]# ./test
is ffffffffffffffff
is 7fffffffffffffff
is 3fffffffffffffff
...
is 1f
is f
is 7
is 3
is 1
is
说明32位ARM芯片上确实实现了64位数。
步骤二:添加测试代码
此处)折叠或打开
问题出现了,test的值没叠加上去。
test = 3;
printf("test0 is %llx\n",test);
test += 1<<32;
("test1 is %llx\n",test);
执行结果如下:
test is 64bit
test0 is 3
test1 is 3
改为test += 0x100000000
执行结果如下:
test0 is 3
test1 is 100000003
结论,1<<32在32位的ARM芯片上是不是默认用一个32位寄存器左移,导致左移溢出,结果就是0?
再加个测试:
此处)折叠或打开
test = 3;
("test0 is %llx\n",test);
+= 0x100000000;
("test1 is %llx\n",test);
= (test&0xffffffff00000000) + 8 ;
("test2 is %llx\n",test);
= (test&0xffffffff) + 1;
("test3 is %llx\n",test);
执行结果如下,完全符合预期:
所以问题解决,正确代码如下:
此处)折叠或打开
unsigned long long ullCurFrmPts=0;//app里用到的时间戳,微秒计
int bf_stamp=0;
int timestamp=0;//SDK提供的时间戳
= ullCurFrmPts&0xffffffff);
if(timestamp*1000 < bf_stamp) {
= (ullCurFrmPts + 0x100000000);
}
ullCurFrmPts = (ullCurFrmPts&0xffffffff00000000)+timestamp*1000;
PS:近一年没写博客了,CU的排版还是这么垃圾,失望至极。