符号扩展到32位,从n位开始 - C

时间:2017-10-05 08:10:03

标签: c bits

我是C的新手并且通过位操作进行练习。

假设我有一个n位的二进制补码数,使得n> 0和n <0 31.如果我事先知道n的大小,我怎么签名将它扩展到32位?

如果n是16位,

int32_t extendMe(int16_t n) {
    return (int32_t) n;
}

假设我有数据定义。

假设我有一个我要签名的n位值扩展到32,我该怎么做呢?

谢谢。

2 个答案:

答案 0 :(得分:2)

如果这真的是将任意位模式解释为使用二进制补码在 n 位中表示的数字,那么这里有一些草率的示例代码:

#include <stdio.h>
#include <inttypes.h>

// this assumes the number is in the least significant `bits`, with
// the most significat of these being the sign bit.
int32_t fromTwosComplement(uint32_t pattern, unsigned int bits)
{
    // read sign bit
    int negative = !!(pattern & (1U << (bits-1)));

    // bit mask for all bits *except* the sign bit
    uint32_t mask = (1U << (bits-1)) - 1;

    // extract value without sign
    uint32_t val = pattern & mask;

    if (negative)
    {
        // if negative, apply two's complement
        val ^= mask;
        ++val;
        return -val;
    }
    else
    {
        return val;
    }
}

int main(void)
{
    printf("%" PRId32 "\n", fromTwosComplement(0x1f, 5)); // output -1
    printf("%" PRId32 "\n", fromTwosComplement(0x01, 5)); // output 1
}

答案 1 :(得分:1)

如果位n - 1为1,则n位2的补码数为负。在这种情况下,您希望用1填充从n到31的所有位。如果它为零,为了完整性,您可能还希望用0填充从n到31的位。因此,您需要一个掩码,您可以使用位操作来完成上述操作。这很容易做到。假设你的n位2的补码数保存在uint32_t中:

int32_t signExtend(uint32_t number, int n)
{
    uint32_t ret;
    uint32_t mask = 0xffffffff << n;
    if (number & (1 << (n - 1)) != 0)
    {
        // number is negative
        ret = number | mask;
    }
    else 
    {
        // number is positive
        ret = number & ~mask;
    }
    return (int32_t) ret;
}

完全未经测试,最后一行可能是UB,但它应该适用于大多数实现。