问题描述
计算机如何在不同大小的有符号整数之间进行转换?
例如,当我将 long long int 值 12000000000 转换为 int 时,它如何减少该值?它如何处理负数?
解决方法
尝试将整数表示形式转换为无法正确表示的较小的有符号类型(例如您尝试将 12000000000 转换为 32 位 int
的示例)是实现定义的行为。来自 this C11 Draft Standard(第三段与此处相关):
6.3.1.3 有符号和无符号整数
1 当一个整数类型的值转换为_Bool以外的其他整数类型时,如果该值可以用新类型表示,则为
不变。
2 否则,如果新类型是无符号的,则通过重复加或减一个新类型可以表示的最大值来转换该值,直到该值在新类型的范围内。60)
3 否则,新类型是有符号的,值不能在其中表示;要么结果是实现定义的,要么引发实现定义的信号
我找到了一个解决方案,它适用于 2s 补码。它可以在宽度上上下转换整数,并且可以处理正负数。
a 是数字, oldp 是符号位的旧位置 newp 是符号位的新位置
uint64_t shsbc(uint64_t a,uint32_t oldp,uint32_t newp) {
if (!(a>>oldp&1)) {
if (oldp > newp) {
return(a & UINT64_MAX>>(64 - (newp + 1)));
} else {
return(a & UINT64_MAX>>(64 - (oldp + 1)));
}
}
if (oldp > newp) {
a &= UINT64_MAX>>((oldp - newp) + 1 + (63 - oldp));
a |= ((uint64_t) 1)<<newp;;
return(a);
} else {
a &= UINT64_MAX>>((newp - oldp) + 1 + (63 - newp));
a |= UINT64_MAX>>(63 - (newp - oldp))<<(newp - oldp - 1);
return(a);
}
}