1. 程式人生 > >C語言中的整型溢位和移位溢位

C語言中的整型溢位和移位溢位

1 整型溢位

原文連結:https://coolshell.cn/articles/11466.html  

  1.1 無符號整型溢位和有符號整型溢位

   對於unsigned整型溢位,C的規範是有定義的——“溢位後的數會以2^(8*sizeof(type))作模運算”,也就是說,如果一個unsigned char(1字元,8bits)溢位了,會把溢位的值與256求模。例如:

1 2 unsignedcharx = 0xff; printf("%d\n", ++x);

上面的程式碼會輸出:0 (因為0xff + 1是256,與2^8求模後就是0)

對於signed整型的溢位

,C的規範定義是“undefined behavior”,也就是說,編譯器愛怎麼實現就怎麼實現。對於大多數編譯器來說,算得啥就是啥。比如:

1 2 signedcharx =0x7f; //注:0xff就是-1了,因為最高位是1也就是負數了 printf("%d\n", ++x);

上面的程式碼會輸出:-128

signed整型溢位規律一般呈環形變化:


1.2 溢位帶來的問題

(1)整形溢位導致死迴圈

#define MAX_LEN 32767

... ...
short len = 0;

while (len < MAX_LEN) {
len += 2;
}
   當short變數len自加到32766時,再次自加就會溢位變成-32768,始終不能大於32767,導致死迴圈發生。

   (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會被提升為unsigned
,而如果我們給len傳一個負數的實參,會通過if的檢查,但在memcpy裡會被提升為一個正數,於是mybuf陣列就overflow了。這個會導致mybuf緩衝區後面的資料被重寫。

2 移位溢位

左移:丟棄最高位,低位補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