C語言打印16進製出現0xffffff現象的問題剖析!

https://www.cnblogs.com/acool/p/4790069.html
今天在博問裏面看到一個朋友的問題,大致是在網絡程序中,打印出來的16進制數,莫名的出現ffffff。例如,某個byte真是值爲0xc9,打印出來確是0xffffffc9。原博問連接如下:http://q.cnblogs.com/q/71073/

其實類似的問題不是隻在網絡程序中才會出現的,看示例代碼:

複製代碼
1 #include <stdio.h>
2 int main()
3 {
4 char c = 0xc9;
5 printf(“A:c = %2x\n”,(unsigned char)c);
6 printf(“B:c = %2x\n”,c & 0xff);
7 printf(“C:c = %2x\n”,c);
8 return 0;
9 }
複製代碼
  程序輸出如下:

A:c = c9
B:c = c9
C:c = ffffffc9
  可以看到:

把c轉換成unsigned char打印是正確的。視作情況A。

把c與 0xff做&操作後打印正確。視作情況B。

對c不做任何處理,則問題復現了,打印出ffffffc9。視作情況C。

情況A B是我百度來的一些解決C現象的方法。那麼我們現在來逐一分析解釋ABC三種情況。

首先我們必須知道,printf()函數的%x(X)輸出的是Int型別的16進制格式。所以char型別的c變量會被轉換成Int型別。

其次,我們的知道計算機是用補碼錶示數據的。關於原碼,反碼,補碼的知識請自行充電。

情況C:

c的補碼:11001001(0xc9)。

c的反碼:11001000(0xc9)。

c的原碼:10110111(0xc9)。

因爲char型別是帶符號的,所以最高位的1這裏視爲負號。

把c轉換成Int型別 char -----> Int

Int_c的原碼:10000000 00000000 00000000 00110111(把c原碼的最高位1 提到最高位。其餘高位補0)。

Int_c的反碼:11111111 11111111 11111111 11001000

Int_c的補碼:11111111 11111111 11111111 11001001(0xffffffc9)。

所以打印出來看似詭異的值其實是合情合理的。如何避免?看AB情況。

情況B:

我們在情況C的基礎上將c與0xff做&操作。

Int_c的補碼:11111111 11111111 11111111 11001001(0xffffffc9)。

&

00000000 00000000 00000000 11111111

最終結果爲: 00000000 00000000 00000000 11001001(0xc9)。

情況A:

我覺得情況A的處理方式纔是最正規的處理辦法,但是據說linux內核使用(&0xff)。

c的補碼:11001001(0xc9)。

c的反碼:11001001(0xc9)。

c的原碼:11001001(0xc9)。

這裏強制轉換c爲unsigned char型別。因此最高位的1不是正負號

把c轉換成Int型別 char -----> Int

Int_c的原碼:00000000 00000000 00000000 11001001(把c原碼的最高位1 提到最高位。其餘高位補0)。

Int_c的反碼:00000000 00000000 00000000 11001001

Int_c的補碼:00000000 00000000 00000000 11001001(0xc9)。

因此打印正常。

以上分析,如有不正確的地方請各位指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章