使用無符號類型要特別注意

一個(gè)由無符號類型引發(fā)的微妙的錯(cuò)誤

#include <stdio.h>  
#include  <string.h>

int main()
{
    char array[] = "hello";
    int d = -1, x;
    //(1)//if (d <= sizeof(array) / sizeof(char))    
    //(2)//if (d <= strlen(array))

    //if (d <= (int)sizeof(array) / sizeof(char))    /*輸出:x = 104*/     
    if (d <= (int)strlen(array))        /*輸出:x = 104*/
    {
        x = array[d + 1];
        printf("x = %d\n", x);  //字符'h'對應(yīng)的ASCII碼是104,   'a'是97
    }
    else
    {
        printf("sizeof(array) / sizeof(char) = %u\n", sizeof(array) / sizeof(char));
        printf("strlen(array) = %u\n", strlen(array));  
      //用%d輸出也是一樣,都是正數(shù)
    }

    return 0;
}
  • 這個(gè)程序若用(1)或(2)的判斷條件會輸出:
    sizeof(array) / sizeof(char) = 6
    strlen(array) = 5
    加上強(qiáng)制類型轉(zhuǎn)換(int)才會輸出:x = 104

(1)原因是sizeof操作符(注意它不是一個(gè)函數(shù)蓝撇,也可以有 sizeof char;sizeof(char);效果一樣)的返回值類型是size_t牺六,而typedef unsigned int size_t;
所以在執(zhí)行表達(dá)式d <= sizeof(array)/sizeof(char)時(shí),右邊表達(dá)式結(jié)果為無符號整型6底挫,因此會將左邊的整型d裝換成無符號整型(-1(在計(jì)算機(jī)中以1的補(bǔ)碼形式存在為二進(jìn)制1111...11111)將變成變成一個(gè)超級大的整數(shù))恒傻,因此判斷結(jié)果是false。

改正方法:d <= (int)sizeof(array)/sizeof(char),人為增加強(qiáng)制類型轉(zhuǎn)換建邓,這樣就不必由編譯器來選擇結(jié)果的類型了盈厘。

(2)同理,strlen()函數(shù)的返回值類型也是size_t官边,而typedef unsigned int size_t;沸手。但是注意strlen()函數(shù)和sizeof操作符的區(qū)別,sizeof會多計(jì)算一個(gè)結(jié)束符'\0'的大小注簿,因此會多1契吉,而strlen()函數(shù)總是只計(jì)算實(shí)際字符串字符個(gè)數(shù)。

改正方法:d <= (int)strlen(array),人為增加強(qiáng)制類型轉(zhuǎn)換诡渴,這樣就不必由編譯器來選擇結(jié)果的類型了捐晶。

對無符號類型的建議(《C專家編程》第24頁)

1、盡量不要在代碼中使用無符號類型,以免增加不必要的麻煩惑灵,尤其是山上,不要僅僅因?yàn)闊o符號類型不存在負(fù)值(如年齡)而用它來表示數(shù)量,可以多增加if-else判斷數(shù)量的合法性也比用無符號類型更安全英支。否則一個(gè)int的 -1佩憾,由編譯器自動(dòng)升級成無符號型int,將會變成一個(gè)非常大的數(shù)潭辈。
2鸯屿、如果用了,應(yīng)該在表達(dá)式中使用強(qiáng)制類型轉(zhuǎn)換把敢,使操作數(shù)均為有符號或者無符號類型寄摆,這樣就不必由編譯器來選擇結(jié)果的類型,可以避免微妙的錯(cuò)誤發(fā)生修赞。
3婶恼、只有在使用位段和二進(jìn)制掩碼時(shí),最好去用無符號數(shù)柏副。這里就要談到正數(shù)和負(fù)數(shù)在計(jì)算機(jī)中的二進(jìn)制存儲方式了勾邦。正數(shù)簡單,就是原碼二進(jìn)制形式存儲割择,如int型32bit位 int a = 1;那么a在計(jì)算機(jī)中存儲為二進(jìn)制000...(總共31個(gè)0)...0001眷篇。但是負(fù)數(shù)就比較復(fù)雜,要用原碼求反碼再加1得到的補(bǔ)碼的二進(jìn)制形式存儲在計(jì)算機(jī)中荔泳,如int b = -1;原碼和a一樣蕉饼,反碼就是111...(總共31個(gè)1)...1110,然后反碼加1得到補(bǔ)碼111...(總共32個(gè)1)...1111玛歌∶粮郏可見b并不是簡單的存儲為二進(jìn)制100...(總共30個(gè)0)...0001。因此在使用位段和二進(jìn)制掩碼這些需要按bit位操作的情況下支子,為了在使用時(shí)讓我們腦子里想的和計(jì)算機(jī)處理的一致创肥,盡量都用無符號類型,就可以避免負(fù)數(shù)在計(jì)算機(jī)中的特殊存儲方式帶來的影響值朋。
《注意:負(fù)數(shù)要以10進(jìn)制輸出時(shí)叹侄,又要將計(jì)算機(jī)中存儲的補(bǔ)碼,先減1求得反碼吞歼,再按位求反得到原碼圈膏,然后將原碼轉(zhuǎn)換成10進(jìn)制輸出并在前面添加一個(gè)‘-’號》

使用無符號類型的優(yōu)缺點(diǎn)

  • 比如int類型和unsigned int類型,同樣是占用4字節(jié)(32bit位)篙骡,int類型的取值范圍是(-2^31到2^31)稽坤,而unsigned int類型的取值范圍是(0到2^32)丈甸,可見在利用正數(shù)的這一半時(shí)無符號數(shù)的可用范圍是有符號的兩倍。有符號數(shù)最高bit位的0或1只能表示+-符號尿褪,不能表示數(shù)值睦擂,浪費(fèi)了。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末杖玲,一起剝皮案震驚了整個(gè)濱河市顿仇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌摆马,老刑警劉巖臼闻,帶你破解...
    沈念sama閱讀 222,865評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異囤采,居然都是意外死亡述呐,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評論 3 399
  • 文/潘曉璐 我一進(jìn)店門蕉毯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乓搬,“玉大人,你說我怎么就攤上這事代虾〗希” “怎么了?”我有些...
    開封第一講書人閱讀 169,631評論 0 364
  • 文/不壞的土叔 我叫張陵棉磨,是天一觀的道長江掩。 經(jīng)常有香客問我,道長乘瓤,這世上最難降的妖魔是什么频敛? 我笑而不...
    開封第一講書人閱讀 60,199評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮馅扣,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘着降。我一直安慰自己差油,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評論 6 398
  • 文/花漫 我一把揭開白布任洞。 她就那樣靜靜地躺著蓄喇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪交掏。 梳的紋絲不亂的頭發(fā)上妆偏,一...
    開封第一講書人閱讀 52,793評論 1 314
  • 那天,我揣著相機(jī)與錄音盅弛,去河邊找鬼钱骂。 笑死叔锐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的见秽。 我是一名探鬼主播愉烙,決...
    沈念sama閱讀 41,221評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼解取!你這毒婦竟也來了步责?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,174評論 0 277
  • 序言:老撾萬榮一對情侶失蹤禀苦,失蹤者是張志新(化名)和其女友劉穎蔓肯,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體振乏,經(jīng)...
    沈念sama閱讀 46,699評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蔗包,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了昆码。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片气忠。...
    茶點(diǎn)故事閱讀 40,918評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖赋咽,靈堂內(nèi)的尸體忽然破棺而出旧噪,到底是詐尸還是另有隱情,我是刑警寧澤脓匿,帶...
    沈念sama閱讀 36,573評論 5 351
  • 正文 年R本政府宣布淘钟,位于F島的核電站,受9級特大地震影響陪毡,放射性物質(zhì)發(fā)生泄漏米母。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評論 3 336
  • 文/蒙蒙 一毡琉、第九天 我趴在偏房一處隱蔽的房頂上張望铁瞒。 院中可真熱鬧,春花似錦桅滋、人聲如沸慧耍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽芍碧。三九已至,卻和暖如春号俐,著一層夾襖步出監(jiān)牢的瞬間泌豆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評論 1 274
  • 我被黑心中介騙來泰國打工吏饿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留踪危,地道東北人蔬浙。 一個(gè)月前我還...
    沈念sama閱讀 49,364評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像陨倡,于是被迫代替她去往敵國和親敛滋。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評論 2 361