最近在做一個C的嵌入式項目,發現在C語言中用printf()函數打印字符型變量時,如果想采用"%x"的格式將字符型變量值以十六進制形式打印出來,會出現一個小問題,如下:
char buf[10] = {0}; buf[0] = 0xbf; printf("%2x\n\n\n", buf[0]); /*在終端將會顯示成:ffffffbf*/ buf[1] = 0x7f; printf("%2x\n\n\n", buf[1]); /*在終端將會顯示成:7f*/
為什麼buf[0]不像buf[1]顯示的那樣,顯示2個十六進制數bf呢?
研究發現,只要字符型變量值的二進制第一位是1,就會如buf[0]所顯示的那樣,出現6個f。
而格式輸出函數printf中會對所輸出的變量做有符號/無符號型的判斷。如果是有符號型變量,且該值二進制首位為1(如我們定義的是char buf[100],且buf[0]中為0xbf),則會按照補碼形式前面全置為1,也就是全為f。(因為終端顯示的是8個十六機制數字;另外,我用Tobor C編譯,因為Tobor C中int是2bytes,終端顯示就成4個十六進制數字了:ffbf,因此我猜測,printf函數顯示之前先將有符號型值轉換成了一個4bytes的int。當然,這是函數內部的處理,跟我們所說的話題關系不大。)。
按照上面述說的,如果把buf聲明為unsigned char型,則顯示會變成:bf
而且,如果程序需要講一個有符號型的變量以十六進制形式輸出,且只顯示兩位,可以強制類型轉換為無符號型變量,如上面的buf[0],可以轉換成:(unsigned char)buf[0]
此外,如果有人這樣來測試這個問題
printf("%2x\n\n\n", 0xbf); /*在終端將會顯示成:bf*/
為什麼這邊沒有6個f呢?因為,printf()函數第二個參數直接以int型來接收,int型變量4bytes,二進制首位自然為0,因此不會顯示多個f。