當printf以十六進制打印char類型數組時引發的bug

以下代碼是我做項目時,遇到的問題,我將以代碼出現的問題,進行此次的總結。
代碼如下:

/*********************************************************************************
 *      Copyright:  (C) 2020 makun<[email protected]>
 *                  All rights reserved.
 *
 *       Filename:  char.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(2020年05月14日)
 *         Author:  makun <[email protected]>
 *      ChangeLog:  1, Release initial version on "2020年05月14日 18時30分44秒"
 *                 
 ********************************************************************************/
#include <stdio.h>


void dump_buf(char *buf, int bytes);

int main (int argc, char **argv)
{

    char buf[5]={0xfd,0xfe,0xff,0xff,0xff};
    dump_buf(buf, 5); 
    return 0;

}
//該函數是以十六進制打印buf數組中的值
void dump_buf(char *buf, int bytes)
{
    int    i;  
    for(i=0; i<bytes; i++)
    {   
        printf("0x%02x ", buf[i]);
        if( 0 == (i+1)%16 )
            printf("\n");
    }
    printf("\n");
}

預期結果:

0xfd 0xfe 0xff 0xff 0xff

實際結果:

0xfffffffd 0xfffffffe 0xffffffff 0xffffffff

下面圖片爲運行後的結果即是實際結果
在這裏插入圖片描述
這是我做項目遇到的一個問題,讓我百思不得奇解,爲什麼會和我預想的不一樣那?於是我就把項目中的這個問題拿出來單獨測試,當我用實驗室服務器寫的時候它竟然跟預期的一樣,代碼跟如上一樣,運行結果如下:
在這裏插入圖片描述
我就覺得這個問題是偶然得,有時候他會出現這樣得錯誤,有時候不會出現這樣得錯誤,前面得代碼沒問題,應該問題是出在用dump_buf函數以十六進制輸出,當我用printf("0x%02x ",(unsigned char) buf[i]);輸出時,這個問題就解決了。在這裏插入圖片描述
對此我開始百度當十六進制打印char和unsigned char爲什麼它們得結果會不一樣,然後就找到了自己想要的答案,對此,我想把我這次學到得知識記錄在這裏,供自己學習。我們先學習一下char和unsigned char的區別吧

char和unsigned char的區別

在內存中,char與unsigned char沒有什麼不同,都是一個字節,唯一的區別是,char的最高位爲符號位,因此char能表示-128~127, unsigned char沒有符號位,因此能表示0~255,這個好理解,8個bit,最多256種情況,因此無論如何都能表示256個數字。

在實際使用過程種有什麼區別呢?

主要是符號位,但是在普通的賦值,讀寫文件和網絡字節流都沒什麼區別,反正就是一個字節,不管最高位是什麼,最終的讀取結果都一樣,只是你怎麼理解最高位而已,在屏幕上面的顯示可能不一樣。

但是我們卻發現在表示byte時,都用unsigned char,這是爲什麼呢?

首先我們通常意義上理解,byte沒有什麼符號位之說,更重要的是如果將byte的值賦給int,long等數據類型時,系統會做一些額外的工作。

如果是char,那麼系統認爲最高位是符號位,而int可能是16或者32位,那麼會對最高位進行擴展(注意,賦給unsigned int也會擴展)而如果是unsigned char,那麼不會擴展。

對於上面這樣的理解我想大家應該理解了吧 ,爲什麼當字節0xfd以有符號和無符號的char打印時值不一樣了吧。當把char裏的值以十六進制打印時,系統認爲最高位是符號位, printf裏隱含地做了一個char到int的轉換,將擴充的位被填充成符號位,符號位爲0和1,因爲以十六進制所以打印的值爲0xfffffffd,ff是十六進制而它的二進制是1111 1111 ,剩下兩個ff的二進制也是一樣的都被填充成了1.

對於以上這個bug是偶然的,但是作爲一個合格的程序員,應該在無論如何要注意這個細節上的問題,畢竟常言:細節決定成功,所以當我們寫代碼時遇到這種問題,一定要用unsigned char來打印數據。

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