我uint16_t在网络协议中使用a 作为序列计数器.这个计数器通常会按预期包装.当接收器获取数据包时,它会根据最近收到的数据来检查此计数器,以查看它是新数据包还是无序数据包.
比较序列号时需要考虑环绕声.因此,如果例如最后的序列号为0x4000,然后从一个序列号0x4001,以0xBFFF较新,且从一个序列号0xC000,以0xFFFF和0x0000到0x3FFF更小.
我目前正在这样做的方式如下:
uint16_t last;
uint16_t current;
...
// read in values for last and current
...
if ((int16_t)(current - last) > 0) {
printf("current is newer\n");
} else {
printf("current is older (or same)\n");
}
Run Code Online (Sandbox Code Playgroud)
通过减去两者并将结果视为a int16_t,我可以很容易地看出哪个更大,哪个更多.因此,例如,如果当前序列号比最后一个序列号少至少5,即((int16_t)(current - last) < -5),我可以假设这不是由于正常的分组重新排序和丢弃分组.
我意识到签名的环绕是未定义的,但是在这种情况下,为了进行比较,我将无符号值视为已签名.这是否会调用未定义的行为,如果是这样,那么进行此类比较的更好方法是什么?
我想要两个无界整数之间的差异,每个整数都由一个uint32_t值表示,该值是取2 ^ 32为模的无界整数。如,例如,TCP序列号。请注意,模数2 ^ 32表示形式可以环绕0,这与更严格的问题不允许环绕0有关。
假定基础无界整数之间的差在正常范围内int。我想要这个带符号的差异值。换句话说,返回一个正常int范围内的值,该值等于两个uint32_t输入模2 ^ 32之差。
例如,0 - 0xffffffff = 1因为我们假设基础无界整数在int范围内。证明:如果A mod 2 ^ 32 = 0且B mod 2 ^ 32 = 0xffffffff,则(A = 0,B = -1)(mod 2 ^ 32)因此(AB = 1)(mod 2 ^ 32)和在int此模级的范围内,具有单个代表1。
我使用了以下代码:
static inline int sub_tcp_sn(uint32_t a, uint32_t b)
{
uint32_t delta = a - b;
// this would work on most systems
return delta;
// …Run Code Online (Sandbox Code Playgroud)