最近有人提到char和unsigned char有什么區別,當然這個問題如果剛學計算機或者編程語言的人來說,非常簡單。我也這么認為,無非就是有符號和無符號的差別嘛。
這個問題讓我想到了以前學習計算機常識的時候關於補碼,原碼,反碼的差異。這里摘取參考文章【1】中的部分內容:
注意:此處的'=='是相等的意思。'='是賦值的意思。
在機器世界里:
正數的最高位是符號位0,負數的最高位是符號位1。
對於正數:反碼==補碼==原碼。
對於負數:反碼==除符號位以外的各位取反。
補碼==反碼+1.
原碼==補碼-1后的反碼==補碼的反碼+1。(讀完本文后,應該能夠直觀地認識到本式的正確性)
可以輕易發現如下規律:
自然計算 :a-b==c.
計算機計算:a-b==a+b的補碼==d.
c的補碼是d.
通過此法,可以把減法運算轉換為加法運算。
所以補碼的設計目的是:
1.使符號位能與有效值部分一起參加運算,從而簡化運算規則.
2.減運算轉換為加運算,進一步簡化計算機中運算器的線路設計.
講的非常清晰了吧,是的。但是在計算機中,常做類型轉換,當char或者unsigned char轉換成int的時候,兩者的差異是顯而易見的。這里采用了部分文章【2】的代碼對轉換過程做了驗證。
1)當我對uch和sch同時賦值-100的時候uch和sch都是十六進制的0x9c
2)此時由於兩者一個是有符號,另一個是無符號的,我們可以看到十進制輸出的時候,無符號的是156,而有符號的,最前面一個bit解釋為了負值 -100
3)然后我們看下對uch進行類型轉換(int)然后看下真值,原碼,反碼和補碼
4)最后我們看下對sch進行類型轉換(int)然后看下真值,原碼,反碼和補碼
可以看出uch和sch最大的差異就是前面的那個符號位,僅僅那一個bit位,對於我們計算機來說,存儲的內容(補碼)將是絕然不同的。
真值,原碼,反碼和補碼轉換代碼請詳見參考文章【2】
- /* 檢查uchar */
- void CheckUchar(unsigned char uch)
- {
- int x;
- char b[MAX+1];
- x = uch;
- printf("CheckUchar Decimal value:%d\n", x);
- TruthValue(b, x);//獲取真值
- printf("TruthValue:\t%s\n", b);
- TrueForm(b, x); //獲取原碼
- printf("TrueForm:\t%s\n", b);
- RadixMinus(b, x);//獲取反碼
- printf("RadixMinus:\t%s\n", b);
- Complement(b, x);//獲取補碼
- printf("Complement:\t%s\n", b);
- }
- /* 檢查schar */
- void CheckSchar(char sch)
- {
- int x;
- char b[MAX+1];
- x = sch;
- printf("CheckSchar Decimal value:%d\n", x);
- TruthValue(b, x);//獲取真值
- printf("TruthValue:\t%s\n", b);
- TrueForm(b, x); //獲取原碼
- printf("TrueForm:\t%s\n", b);
- RadixMinus(b, x);//獲取反碼
- printf("RadixMinus:\t%s\n", b);
- Complement(b, x);//獲取補碼
- printf("Complement:\t%s\n", b);
- }
- int main()
- {
- unsigned char uch = -100;
- char sch = -100;
- printf("hex: uch = 0x%x, sch = 0x%x\n", uch, sch);
- printf("dec: uch = %d, sch = %d\n", uch, sch);
- CheckUchar(uch);
- CheckSchar(sch);
- return 0;
- }
參考文章:
【2】閑扯原碼,補碼和反碼