c++ - 如何在C语言中检测环绕计数器和大负值之间的区别

标签 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);
        }

这里的想法是在 RTP 时间戳中捕获无效的大增量。我们有一个当前时间戳和一个从对等 RTP 客户端接收的先前时间戳。 RTP 时间戳无效值的边界限制为 -4294959295 < rtpDelta < -3600,如果 Delta 小于 -3600 且大于 -4294959295,则应抛出错误,因为接近 UMAX_INT 的值将被视为翻转.我在这里做错了什么?

最佳答案

一般来说,如果你有两个无符号计数器 ab,其值介于 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 使用任何无符号整数类型作为 ab 将产生正确的结果,其中 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/

相关文章:

头文件中的 C++ operator<< 和 >> 方法,做的非常错误

c++ - 我可以命名从接口(interface)派生的每个类吗?

c - 填充结构的实际大小,(成员大小的总和,没有用于对齐的填充)

c - 多精度加法的意外表现

c++ - 如何获得 "static const unsigned char my_var[]"的长度

c++ - 如何使用.h 文件中的按钮单击事件调用.cpp 的功能?

c++ - 运行目标对于运行方案 Xcode 无效

c - 在 C 编程语言的声明时初始化二维数组

c++ - PIC 寄存器 (%ebx) 有什么作用?

python - 汇编和Python之间的传输