c語言中 char* 和 unsigned char* 的區別淺析(轉)


原文:https://blog.csdn.net/guotianqing/article/details/77341657

 

背景
最近在項目中遇到了一個編譯警告,是因為定義的變量為char[],而在使用時作為函數的unsigned char*類型的參數調用。這個警告很容易避免,但是char*和unsigned char*到底有什么區別呢,本文作一個簡單的探討。

char 和 unsigned char 的區別
在C中,默認的基礎數據類型均為signed,如定義變量為int,long等,都為有符號的。如果要定義無符號類型,必須顯式地在變量類型前加unsigned。

char vs unsigned char
相同點:在內存中都是一個字節,8位(2^8=256),都能表示256個數字
不同點:char的最高位為符號位,因此char能表示的數據范圍是-128~127,unsigned char沒有符號位,因此能表示的數據范圍是0~255

實際使用中,如普通的賦值,讀寫文件和網絡字節流都沒有區別,不管最高位是什么,最終的讀取結果都一樣,在屏幕上面的顯示可能不一樣。

但是要把一個char類型的變量賦值給int、long等數據類型或進行類似的強制類型轉換時時,系統會進行類型擴展,這時區別就大了。對於char類型的變量,系統會認為最高位為符號位,然后對最高位進行擴展,即符號擴展。若最高位為1,則擴展到int時高位都以1填充。對於unsigned char類型的變量,系統會直接進行無符號擴展,即0擴展。擴展的高位都以0填充。所以在進行類似的操作時,如果char和unsigned char最高位都是0,則結果是一樣的,若char最高位為1,則結果會大相徑庭。

可以使用的下面的小程序驗證一下:

#include <stdio.h>

static void func(unsigned char uc)
{
    char c;
    int i, j;
    unsigned int ui, uj;

    c = uc;
    i = (int)c;
    j = (int)uc;
    ui = (unsigned int)c;
    uj =(unsigned int)uc;
    printf("%%c: %c, %c\n", c, uc);
    printf("%%x: %x, %x\n", c, uc);
    printf("%%u: %u, %u\n", ui, uj);
    printf("%%d: %d, %d\n", i, j);
}

int main(int argc, char *argv[])
{
    func(0x80);
    func(0x7f);

    return 0;
}

  

運行結果如下:

%c: �, �
%x: ffffff80, 80
%u: 4294967168, 128
%d: -128, 128
---------------------------
%c:,
%x: 7f, 7f
%u: 127, 127
%d: 127, 127

 


對於char來說,0x80用二進制表示為1000 0000,當它作為char賦值給unsigned int或 int 時,系統認為最高位是符號位,會對最高位進行擴展。而0x7F用二進制表示為0111 1111,最高位為0,不會擴展。對於unsigned char來說,不管最高位是0,還是1,都不會做擴展。

char* 和 unsigned char*的區別
char* 和 unsigned char* 也具有類似的區別,如下面測試程序所示:

 

char*是有符號的,如果大於127即0x7F的數就是負數了,使用%x格式化輸出,系統自動進行了符號擴展,就會產生變化。

所以在涉及到類型提升的上下文中,要注意使用char*和unsinged char*的區別。

#include <stdio.h>

int main(int argc, char *argv[])
{
    unsigned char k = 0;
    int i = -1;
    short a = -12345;
    char *p;
    unsigned char *q;

    printf("sizeof(i) = %d\n",sizeof(i));
    printf("sizeof(a) = %d\n",sizeof(a));
    printf("-----------------------------\n");
    printf("begin p(char):\n");
    p = (char*)&a;
    printf("a = %u | %d\n",a,a);
    for(k=0;k<sizeof(a);k++)
    {
        printf("0x%x ",*(p++));
    }
    printf("\n");
    p = (char*)&i;
    printf("i = %u | %d\n",i,i);
    for(k=0;k<sizeof(i);k++)
    {
        printf("0x%x ",*(p++));
    }
    printf("\n");
    printf("-1 > 0u: %s\n",(-1>0u ? "true":"false"));

    printf("-----------------------------\n");
    printf("begin q(unsigned char):\n");
    q = (unsigned char*)&a;
    printf("a = %u | %d\n",a,a);
    for(k=0;k<sizeof(a);k++)
    {
        printf("0x%x ",*(q++));
    }
    printf("\n");
    q = (unsigned char*)&i;
    printf("i = %u | %d\n",i,i);
    for(k=0;k<sizeof(i);k++)
    {
        printf("0x%x ",*(q++));
    }
    printf("\n");
    printf("-1 > 0u: %s\n",(-1>0u ? "true":"false"));

    return 0;
}

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM