C語言中的整型溢位和移位溢位
阿新 • • 發佈:2019-01-25
1 整型溢位
原文連結:https://coolshell.cn/articles/11466.html
1.1 無符號整型溢位和有符號整型溢位
對於unsigned整型溢位,C的規範是有定義的——“溢位後的數會以2^(8*sizeof(type))作模運算”,也就是說,如果一個unsigned char(1字元,8bits)溢位了,會把溢位的值與256求模。例如:
1 2 |
unsigned char x
= 0xff;
printf ( "%d\n" ,
++x);
|
上面的程式碼會輸出:0 (因為0xff + 1是256,與2^8求模後就是0)
對於signed整型的溢位 ,C的規範定義是“undefined behavior”,也就是說,編譯器愛怎麼實現就怎麼實現。對於大多數編譯器來說,算得啥就是啥。比如:
1 2 |
signed char x
=0x7f; //注:0xff就是-1了,因為最高位是1也就是負數了
printf ( "%d\n" ,
++x);
|
上面的程式碼會輸出:-128
signed整型溢位規律一般呈環形變化:
1.2 溢位帶來的問題
(1)整形溢位導致死迴圈
當short變數len自加到32766時,再次自加就會溢位變成-32768,始終不能大於32767,導致死迴圈發生。#define MAX_LEN 32767 ... ... short len = 0; while (len < MAX_LEN) { len += 2; }
(2)型別轉換帶來的溢位問題
int copy_something(char *buf, int len)
{
#define MAX_LEN 256
char mybuf[MAX_LEN];
... ...
if(len > MAX_LEN){ // [1]
return -1;
}
return memcpy(mybuf, buf, len);
}
函式入參len是signed int型別,而memcpy第三個引數型別是size_t(一般為unsigned 型別)。於是,len會被提升為unsigned2 移位溢位
左移:丟棄最高位,低位補0
右移:對於有符號數,正數補0,負數補1
左移和右移運算過程中也會發生溢位,移位位數並不是可以任意。當移位位數超過該數值型別的最大位數時,編譯器會用移位位數去模該型別位數,然後按照餘數進行移位。
例如:左移溢位
int main()
{
int i=1;
i=i<<33;
printf("%d\n",i);
return 0;
}
結果:
2
左移位數為33,變數i為32位,故左移位數實際為:33%32=1,結果為2