c語言之char*和unsigned?char*的區(qū)別及說明
最近在項(xiàng)目中遇到了一個(gè)編譯警告,是因?yàn)槎x的變量為char[],而在使用時(shí)作為函數(shù)的unsigned char*類型的參數(shù)調(diào)用。
這個(gè)警告很容易避免,但是char*和unsigned char*到底有什么區(qū)別呢?
char 和 unsigned char 的區(qū)別
在C中,默認(rèn)的基礎(chǔ)數(shù)據(jù)類型均為signed,如定義變量為int,long等,都為有符號(hào)的。如果要定義無符號(hào)類型,必須顯式地在變量類型前加unsigned。
char vs unsigned char
- 相同點(diǎn):在內(nèi)存中都是一個(gè)字節(jié),8位(2^8=256),都能表示256個(gè)數(shù)字
- 不同點(diǎn):char的最高位為符號(hào)位,因此char能表示的數(shù)據(jù)范圍是-128~127,unsigned char沒有符號(hào)位,因此能表示的數(shù)據(jù)范圍是0~255
實(shí)際使用中,如普通的賦值,讀寫文件和網(wǎng)絡(luò)字節(jié)流都沒有區(qū)別,不管最高位是什么,最終的讀取結(jié)果都一樣,在屏幕上面的顯示可能不一樣。
但是要把一個(gè)char類型的變量賦值給int、long等數(shù)據(jù)類型或進(jìn)行類似的強(qiáng)制類型轉(zhuǎn)換時(shí)時(shí),系統(tǒng)會(huì)進(jìn)行類型擴(kuò)展,這時(shí)區(qū)別就大了。對(duì)于char類型的變量,系統(tǒng)會(huì)認(rèn)為最高位為符號(hào)位,然后對(duì)最高位進(jìn)行擴(kuò)展,即符號(hào)擴(kuò)展。若最高位為1,則擴(kuò)展到int時(shí)高位都以1填充。
對(duì)于unsigned char類型的變量,系統(tǒng)會(huì)直接進(jìn)行無符號(hào)擴(kuò)展,即0擴(kuò)展。擴(kuò)展的高位都以0填充。所以在進(jìn)行類似的操作時(shí),如果char和unsigned char最高位都是0,則結(jié)果是一樣的,若char最高位為1,則結(jié)果會(huì)大相徑庭。
可以使用的下面的小程序驗(yàn)證一下:
#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; }
運(yùn)行結(jié)果如下:
%c: ?, ?
%x: ffffff80, 80
%u: 4294967168, 128
%d: -128, 128
---------------------------
%c:,
%x: 7f, 7f
%u: 127, 127
%d: 127, 127
對(duì)于char來說,0x80用二進(jìn)制表示為1000 0000,當(dāng)它作為char賦值給unsigned int或 int 時(shí),系統(tǒng)認(rèn)為最高位是符號(hào)位,會(huì)對(duì)最高位進(jìn)行擴(kuò)展。而0x7F用二進(jìn)制表示為0111 1111,最高位為0,不會(huì)擴(kuò)展。
對(duì)于unsigned char來說,不管最高位是0,還是1,都不會(huì)做擴(kuò)展。
char* 和 unsigned char*區(qū)別說明
char* 和 unsigned char* 也具有類似的區(qū)別,如下面測(cè)試程序所示:
#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; }
輸出結(jié)果為:
sizeof(i) = 4
sizeof(a) = 2
-----------------------------
begin p(char):
a = 4294954951 | -12345
0xffffffc7 0xffffffcf
i = 4294967295 | -1
0xffffffff 0xffffffff 0xffffffff 0xffffffff
-1 > 0u: true
-----------------------------
begin q(unsigned char):
a = 4294954951 | -12345
0xc7 0xcf
i = 4294967295 | -1
0xff 0xff 0xff 0xff
-1 > 0u: true
char*是有符號(hào)的,如果大于127即0x7F的數(shù)就是負(fù)數(shù)了,使用%x格式化輸出,系統(tǒng)自動(dòng)進(jìn)行了符號(hào)擴(kuò)展,就會(huì)產(chǎn)生變化。
所以在涉及到類型提升的上下文中,要注意使用char*和unsinged char*的區(qū)別。
幾個(gè)區(qū)別:const char *, unsigned char *
1.char*是有符號(hào)的, 如果大于127即0x7F的數(shù)就是負(fù)數(shù)了,使用%x格式化輸出,就會(huì)產(chǎn)生變化,所以使用%x格式化輸出數(shù)據(jù)時(shí),記得一定要轉(zhuǎn)換成無符號(hào)類型;
2.char *是字符串,以'/0'為結(jié)束符,unsigned char *是普通的指針;
3.有符號(hào)的字符型數(shù)據(jù)C7,CF分別傳入printf,此時(shí)會(huì)將類型提升為int,由于是有符號(hào)數(shù),所以符號(hào)位要進(jìn)行擴(kuò)展,得到FFFFFFCF和FFFFFFC7。無符號(hào)的字符型數(shù)據(jù)C7,CF分別傳入printf,此時(shí)會(huì)將類型提升為unsigned int,由于無符號(hào)數(shù)不進(jìn)行符號(hào)位擴(kuò)展,所以得到000000CF和00000C7。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
visual?studio?2022?編譯出來的文件被刪除并監(jiān)視目錄中的文件變更(示例詳解)
這篇文章主要介紹了visual?studio?2022?編譯出來的文件被刪除?并監(jiān)視目錄中的文件變更,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08Opencv Hough算法實(shí)現(xiàn)圖片中直線檢測(cè)
這篇文章主要為大家詳細(xì)介紹了Opencv Hough算法實(shí)現(xiàn)圖片中直線檢測(cè),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12C++實(shí)現(xiàn)std::set的示例項(xiàng)目
std::set是C++標(biāo)準(zhǔn)庫中的關(guān)聯(lián)容器,提供有序唯一元素集合,本文就來介紹一下std::set的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下2025-02-02C語言詳細(xì)分析講解關(guān)鍵字goto與void的作用
我們?cè)贑語言中經(jīng)常會(huì)見到void,也會(huì)偶爾見到goto,那么C語言中既然有g(shù)oto,為什么我們?cè)诖a中見的很少呢?在以前很多的項(xiàng)目經(jīng)驗(yàn)中,我們得到這樣一條潛規(guī)則:一般項(xiàng)目都是禁用goto的,程序質(zhì)量與goto的出現(xiàn)次數(shù)成反比。自后也就造成了我們一般不會(huì)使用goto2022-04-04C++?Qt實(shí)現(xiàn)一個(gè)解除文件占用小工具
這篇文章主要為大家詳細(xì)介紹了如何利用C++?Qt實(shí)現(xiàn)一個(gè)解除文件占用小工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-09-09C++原地刪除有序數(shù)組重復(fù)項(xiàng)的N種方法
給定一個(gè)排序數(shù)組,你需要在原地刪除重復(fù)出現(xiàn)的元素,使得每個(gè)元素只出現(xiàn)一次,返回移除后數(shù)組的新長度,不要使用額外的數(shù)組空間,你必須在 原地 修改輸入數(shù)組 并在使用O(1)額外空間的條件下完成,故本文介紹了C++原地刪除有序數(shù)組重復(fù)項(xiàng)的N種方法,需要的朋友可以參考下2025-03-03