相关疑难解决方法(0)

通过强制转换检测未签名的环绕到签名的未定义行为?

uint16_t在网络协议中使用a 作为序列计数器.这个计数器通常会按预期包装.当接收器获取数据包时,它会根据最近收到的数据来检查此计数器,以查看它是新数据包还是无序数据包.

比较序列号时需要考虑环绕声.因此,如果例如最后的序列号为0x4000,然后从一个序列号0x4001,以0xBFFF较新,且从一个序列号0xC000,以0xFFFF0x00000x3FFF更小.

我目前正在这样做的方式如下:

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),我可以假设这不是由于正常的分组重新排序和丢弃分组.

我意识到签名的环绕是未定义的,但是在这种情况下,为了进行比较,我将无符号值视为已签名.这是否会调用未定义的行为,如果是这样,那么进行此类比较的更好方法是什么?

c casting undefined-behavior

12
推荐指数
1
解决办法
463
查看次数

如何在不损失结果范围的情况下将C中的uint转换为int

我想要两个无界整数之间的差异,每个整数都由一个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)

c math language-lawyer

5
推荐指数
1
解决办法
131
查看次数

标签 统计

c ×2

casting ×1

language-lawyer ×1

math ×1

undefined-behavior ×1