符号扩展到 32 位,从 n 位开始 - C
Sign extending to 32 bits, starting with n bits - C
我是 C 的新手,正在练习位操作。
假设我有一个 n 位二进制补码,使得 n > 0 且 n < 31。如果我事先知道 n 的大小,我如何将它符号扩展到 32 位?
如果n是16位,
int32_t extendMe(int16_t n) {
return (int32_t) n;
}
假设我有数据定义。
假设我有一个 n 位的值要签名扩展到 32,我该如何完成?
谢谢。
如果这真的是关于将任意位模式解释为使用二进制补码以 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
}
如果第 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,但它应该适用于大多数实现。
我是 C 的新手,正在练习位操作。
假设我有一个 n 位二进制补码,使得 n > 0 且 n < 31。如果我事先知道 n 的大小,我如何将它符号扩展到 32 位?
如果n是16位,
int32_t extendMe(int16_t n) {
return (int32_t) n;
}
假设我有数据定义。
假设我有一个 n 位的值要签名扩展到 32,我该如何完成?
谢谢。
如果这真的是关于将任意位模式解释为使用二进制补码以 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
}
如果第 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,但它应该适用于大多数实现。