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)
从标准的角度来看,这是否可以保证正常工作?
您可以使用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 ++中的未定义行为。)