Bla*_*ero 5 c c++ x86 32-bit rtp
为我的愚蠢道歉,因为这是我在这个论坛上的第一篇文章.我试图通过以下代码检测包装无符号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);
}
Run Code Online (Sandbox Code Playgroud)
这里的想法是在RTP时间戳中捕获无效的大型Deltas.我们有一个当前的TimeStamp和一个从对等RTP客户端接收的前一个Timestamp.RTP时间戳的无效值的边界限制是-4294959295 <rtpDelta <-3600,如果Delta小于-3600且大于-4294959295,它应该抛出错误,因为更接近UMAX_INT的值将被视为翻转.我在这做错了什么?
一般来说,如果您有两个无符号计数器a
和b
,其值在 0 和LIMIT-1
之间(含 0 和 ),且数据类型能够表示2*LIMIT-1
,则可以使用中间分割点的模算术:
difference = (a + LIMIT - b) % LIMIT;
if (difference <= LIMIT/2) {
/* a = b + difference */
} else {
/* b = a + (LIMIT - difference) */
}
Run Code Online (Sandbox Code Playgroud)
通常是LIMIT
2 的幂,在这种情况下,模运算符 ( % LIMIT
) 可以替换为二进制 AND ( & (LIMIT-1)
),这在当前处理器上要快得多。
对于 C,无符号整数类型在标准中定义为具有模运算(C99、C11 6.2.5p9),因此a - b
使用任何无符号整数类型 fora
和b
将产生正确的结果,并且是头文件中定义LIMIT
的相应宏。例如,Utype_MAX
"limits.h"
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) */
Run Code Online (Sandbox Code Playgroud)
考虑:
unsigned int LowerBound = -3600u, UpperBound = 4800000u;
unsigned int difference = currRTPTs - prevRTPTs;
Run Code Online (Sandbox Code Playgroud)
观察到,由于环绕, , , 的值LowerBound
将-3600u
是一个很大的正整数。现在,当数学差值(在不溢出的情况下计算)小于 -3600 一个合理的量时, 的值difference
将是一个大整数,并且它将小于LowerBound
。此外,如果差异没有变得太大(在负方向上),则将difference
保持大于UpperBound
。
同样,如果差异大于 4,800,000 且合理,则 的值difference
将大于UpperBound
。如果差异没有变得太大,那么它将保持小于LowerBound
。
difference
因此,在这两种情况下,当数学差异超出所需范围(但不是太多)时的值小于LowerBound
和大于UpperBound
:
if (difference < LowerBound && difference > UpperBound)
printf("Delta in timestamps is outside acceptable bounds.\n");
Run Code Online (Sandbox Code Playgroud)
请注意,当数学差异超过-3600u
(即 4,294,967,296 - 3600)或小于 4,800,000 - 4,294,967,296 时,此操作将会失败。因此,当差异在 [-4,290,167,296, 4,294,963,696] 范围内时,测试有效。