为我的愚蠢道歉,因为这是我在这个论坛上的第一篇文章。我试图在以下代码的帮助下检测环绕无符号 32 位计数器和大型负跳转之间的区别,但编译器给我错误:
错误:由于数据类型的范围有限,比较始终为真 [-Werror=type-limits]
这是我的代码片段:
#define MAX_BACKWARD_JUMP -4294959295 //UINT_MAX - 8000
#define MIN_BACKWARD_JUMP -3600
#define MAX_FORWARD_JUMP 4800000
signed int rtpDelta; //Signed 32-bit
unsigned int currRTPTs, prevRTPTs; //unsigned 32-bit
rtpDelta = currRTPTs - prevRTPTs;
if ((rtpDelta > MAX_BACKWARD_JUMP && rtpDelta < MIN_BACKWARD_JUMP)
|| (rtpDelta > MAX_FORWARD_JUMP))
{
printf("Delta in Timestamps too large\n",rtpDelta);
}
这里的想法是在 RTP 时间戳中捕获无效的大增量。我们有一个当前时间戳和一个从对等 RTP 客户端接收的先前时间戳。 RTP 时间戳无效值的边界限制为 -4294959295 < rtpDelta < -3600,如果 Delta 小于 -3600 且大于 -4294959295,则应抛出错误,因为接近 UMAX_INT 的值将被视为翻转.我在这里做错了什么?
最佳答案
一般来说,如果你有两个无符号计数器 a
和 b
,其值介于 0 和 LIMIT-1
之间,包括这两个值,并且能够表示 2*LIMIT-1
的数据类型,您可以使用中间分割点的模运算:
difference = (a + LIMIT - b) % LIMIT;
if (difference <= LIMIT/2) {
/* a = b + difference */
} else {
/* b = a + (LIMIT - difference) */
}
通常 LIMIT
是 2 的幂,在这种情况下,模运算符 (% LIMIT
) 可以替换为二进制 AND ( & (LIMIT-1)
),这在当前处理器上要快得多。
对于 C,无符号整数类型在标准中被定义为具有模运算(C99、C11 6.2.5p9),因此 a - b
使用任何无符号整数类型作为 a
和 b
将产生正确的结果,其中 LIMIT
是 "limits.h"中定义的相应
头文件。例如,Utype_MAX
宏
const unsigned int d = (unsigned int)a - (unsigned int)b;
if (d <= UINT_MAX/2)
/* a >= b, a = b + d */
else
/* a < b, b = a + UINT_MAX - (d - 1) */
关于c++ - 如何在C语言中检测环绕计数器和大负值之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21810258/