我想要两个无界整数之间的差,每个整数由uint32_t
值表示,该值是取2 ^ 32为模的无界整数。如,例如,TCP序列号。请注意,与more restricted questions that do not allow wrapping around 0不同, modulo 2 ^ 32 表示形式可以环绕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;
// what is the language-safe way to do this?
}
这在大多数系统上都有效,因为它们对uint
和int
都使用模2 ^ 32表示形式,并且普通的模2 ^ 32减法是在此处生成的唯一合理的汇编代码。
但是,我相信C标准仅在delta>=0
时定义上述代码的结果。例如,在this question上,一个答案是:
如果我们将超出范围的值分配给带符号类型的对象,则 结果不确定。该程序似乎可以运行,可能会崩溃, 否则可能会产生垃圾值。
如何根据C标准从uint
到int
进行模2 ^ 32转换?
注意:我希望答案代码不包含条件表达式,除非您可以证明它是必需的。 (在代码说明中进行案例分析就可以了。)