C 有符号到有符号整数的转换是如何工作的? 6.3.1.3 有符号和无符号整数

问题描述

计算机如何在不同大小的有符号整数之间进行转换?

例如,当我将 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);
    }
}