无符号整数的差异-标准的支持方式来获得有符号结果?

vla*_*sch 13 c language-lawyer

假设有两个任意时间戳记:

uint32_t timestamp1;    
uint32_t timestamp2;
Run Code Online (Sandbox Code Playgroud)

除了转换为更大的带符号类型的明显变体和相当冗长的if-else之外,是否有一种标准的一致方式来获得两者的带符号区别。

事先不知道哪一个较大,但是已知差异不大于最大20位,因此它将适合32位带符号。

int32_t difference = (int32_t)( (int64_t)timestamp1 - (int64_t)timestamp2 );
Run Code Online (Sandbox Code Playgroud)

该变体的缺点是硬件可能不支持使用64位算术,并且只有存在较大的类型时(当然,时间戳已经是64位),这当然是可能的。

其他版本

int32_t difference;
if (timestamp1 > timestamp2) {
  difference =    (int32_t)(timestamp1 - timestamp2);
} else {
  difference = - ((int32_t)(timestamp2 - timestamp1));
}
Run Code Online (Sandbox Code Playgroud)

非常冗长,涉及条件跳转。

那是

int32_t difference = (int32_t)(timestamp1 - timestamp2);
Run Code Online (Sandbox Code Playgroud)

从标准的角度来看,这是否可以保证正常工作?

Bat*_*eba 8

您可以使用union基于

typedef union
{
    int32_t _signed;
    uint32_t _unsigned;
} u;
Run Code Online (Sandbox Code Playgroud)

unsigned算术方式执行计算,将结果分配给_unsigned成员,然后读取的_signed成员union作为结果:

u result {._unsigned = timestamp1 - timestamp2};
result._signed; // yields the result
Run Code Online (Sandbox Code Playgroud)

它可以移植到实现我们所依赖的固定宽度类型的任何平台上(它们不需要)。对于有符号成员,保证2的补码,并且在“机器”级别,2的补码有符号算术与无符号算术没有区别。这里没有转换或memcpy-type开销:一个好的编译器将编译出本质上是标准的语法糖。

(请注意,这是C ++中的未定义行为。)