我是C新手,並通過位操作獲得了一些練習。符號擴展到32位,從n位開始 - C
假設我有n位二進制補碼數使得n> 0和n < 31.如果我知道的n提前大小,我怎麼能簽字擴展到32位?
如果n爲16位,
int32_t extendMe(int16_t n) {
return (int32_t) n;
}
假設我有數據的定義。
假設我有一個我想簽名的n位值可以擴展到32位,我該怎麼做到這一點?
謝謝。
我是C新手,並通過位操作獲得了一些練習。符號擴展到32位,從n位開始 - C
假設我有n位二進制補碼數使得n> 0和n < 31.如果我知道的n提前大小,我怎麼能簽字擴展到32位?
如果n爲16位,
int32_t extendMe(int16_t n) {
return (int32_t) n;
}
假設我有數據的定義。
假設我有一個我想簽名的n位值可以擴展到32位,我該怎麼做到這一點?
謝謝。
如果這真的是關於如何解釋任意位模式爲使用二進制補碼在ň位表示的數字,這裏的一些草率的示例代碼這樣做:
#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位2的補數是負的,如果位n - 1是1.在這種情況下,您想要用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,但它應該在大多數實施工作。
你的意思是你想對二進制補碼進行操作,而不管你的編譯器使用負數的表示嗎?或者這只是一個假設?如果您確實是指前者,則必須使用**無符號**類型來完全控制所有(值)位。 –
啊,是的,這就是我的意思。 – Kyle
這通常會作爲[integer promotion](http://en.cppreference.com/w/c/language/conversion#Integer_promotions)的一部分自動發生,例如,當編譯器執行[常規算術轉換](http:///en.cppreference.com/w/c/language/conversion#Usual_arithmetic_conversions)。 –