2017-09-11 51 views
3

如何從無符號字符檢索負值。從無符號字符(Little Endian)中檢索正或負n位

說我有無符號的字符,我通過了樂趣,只是想獲得第一個6位。現在這些6位可以具有從其他函數填充的正值或負值。我想提取相同的價值。 我可以使用0x3F成功提取正值。但是,怎麼樣,如果它有負值例如

signed char my_6bitfunc( unsigned char *val) 
{ 
    unsigned char temp = *val & 0x3F; 
    return temp; 
} 

// somewhere in main 
int main() 
{ 
    signed char valneg = -31 ; 
    signed char valpos = 31 ; 

    signed char a = my_6bitfunc(&valneg); 
    signed char b = my_6bitfunc(&valpos); 

    printf(" val neg %d\n", a); // not -31 but 33 ? 
    printf(" val positive %d\n", b); 
} 

O/P
預期值的-31 =實際值= 33,爲什麼?錯誤
b = 31的預期值實際值= 31正確。

+0

在'my_6bitfunc'爲什麼''temp' unsigned'? – MotKohn

+0

@ MotKohn,即使簽名也沒有什麼區別。我正在返回簽名字符。我認爲我在這裏看到的是額外的操作像xor或類似的東西給我預期的價值,但沒有線索添加 – samprat

+0

如果函數調用-75時,你想要什麼結果? – 4386427

回答

3

要標記擴展一個二進制補碼字段,請使用((x^N) - N) - 其中N是符號位的數字表示形式,例如16位的32768。

signed char my_6bitfunc (unsigned char *val) 
{ 
    unsigned char temp = *val & 0x3FU; 
    return ((signed char)(temp^0x20U)) - 0x20; 
} 
+0

我做了類似的事情temp =(temp^0x20) - 0x20;現在獲得預期的價值。但仍然不能理解我們爲什麼要異或者減去以及如何得到正確的價值?例如0x3D XOR 0x20 = 0x1F(dec中爲31)。現在1F-0X20? ...我知道Iam獲得正確的價值,但可以請你向我解釋 – samprat

+0

繼續。當我在計算器中減去1F-0x20時,我得到了111111111111.如何返回簽名的temp使其正確? – samprat

+2

0x20是符號位;您可以將其視爲具有-2^5的值,而其他位具有值2^4 2^3 ... 2^0。 XOR反轉符號位,位5;如果它是零,我們已經增加了2^5;如果是一個,我們減去2^5。現在通過減去2^5,如果符號位爲零,我們恢復加入的2^5,如果符號位爲1,則減去2^5我們需要二進制補碼。 –

0

那麼,你不能掩蓋負數的2高位。

爲什麼不呢?

那麼,2的補位和8位字符變量(這是最常見的),你有:

-31 -> 11100001 

如果你掩蓋由0x3F的你會得到

00100001 

這正是33爲8位2的補碼有符號數。因此,你的程序打印33.

一般來說,你不能玩在計算機中的數字的基本表示。在大多數系統中,無法用6位表示有符號數並使用8位格式打印。這是不可能的。

但是,您可以編寫一個函數,將8位有符號數的範圍限制爲6位有符號數。 C標準爲您提供了在不同位數的類型之間進行轉換時如何完成的線索。您可以實施類似的轉換。

一個6位帶符號2的補碼可以保持-32到31.所以如果你的轉換函數-75的輸入你應該繼續添加31 + 1(即MAX + 1)到輸入,直到它在有效範圍內範圍。

-75 + (31+1) = -43 
-43 + (31+1) = -11 (which is in range) 

但在二進制級別,你需要將其保存爲11110101您的電腦最有可能使用8位作爲其最小整型。

如果你知道輸入的範圍是-32和-1(和不喜歡的轉換,當輸入小於-32)之間,你可以離開二元格局不變爲負數。像:

#include <stdio.h> 

signed char my_6bitfunc( signed char *val) 
{ 
    if (*val < 0) return *val; // Add this line 
    return *val & 0x3F;; 
} 

int main() 
{ 
    signed char valneg = -31 ; 
    signed char valpos = 31 ; 

    signed char a = my_6bitfunc(&valneg); 
    signed char b = my_6bitfunc(&valpos); 

    printf(" val neg %d\n", a); // not -31 but 33 ? 
    printf(" val positive %d\n", b); 
} 

輸出:

val neg -31 
val positive 31 
+0

所有我感興趣的是6bit具有負值和正值的一些func填充。其他mSb由其他功能填充。所以我需要提取有符號和無符號val的第一個6位 – samprat