天天看點

C++:防止int32溢出--以反轉數字為例

int32溢出

  • 在C++等語言中int類型的整數占4個位元組(一般而言),而一個位元組是8bit,是以int型可表示32位的整數,又因為int可以表示負數,是以int的範圍是 − 2 31 -2^{31} −231~ 2 31 2^{31} 231-1
  • 如果用數字表示,就是:-2147483648 ~ 2147483647
  • 而在C++裡可用關鍵字INT_MAX和INT_MIN表示上述的int上限和int下限

溢出的後果

  • 對于int型的溢出,編譯器可能會依二進制計算結果根據補碼的規則得到一個錯誤的結果
  • 可能造成緩沖區溢出、未知的邏輯錯誤

防止int32溢出

錯誤的思路:判斷一個int是否大于INT_MAX或小于INT_MIN

如果int已經溢出,編譯器要麼會報錯,要麼會處理這個數字使其處于int允許的範圍内(當然這不是我們想要的數字),是以這樣的比較沒有意義,無法判斷是否溢出。

正确的思路:在無法判斷一個操作是否會造成溢出時,在操作之前加一個判斷語句。判斷什麼呢?打個比方,我們要進行 a+b 的操作(a,b>0),但我們無法判斷 a+b 是否會溢出,正如前面所說,我們不能通過 a+b>INT_MAX 這種方式去判斷,但是可以轉換一下思路,判斷 a>INT_MAX-b 是否為真,若為真,a+b會溢出,否則不會

可能面對具體問題的時候需要一點微調和補充,但基本的思路就是這樣,萬變不離其宗。

示例

這裡給出一個程式用作示例,這是一個很經典的問題–将一個數字反轉,轉換很簡單,現在考慮的是如何防止倒置過程中發生溢出。規定如果發生溢出,傳回0。

int reverse(int x) {
   	int ans = 0;
   	int temp = 0;
   	int r = 0;
   	if (x >= 0)
   		while (x) {
   			r = x % 10;
   			if (INT_MAX / 10 < temp) return 0;
   			temp = ans * 10;
   			if (INT_MAX - r < temp) return 0;
   			ans = temp + r;
   			temp = ans;
   			x /= 10;
   		}
   	else 
   		while (x) {
   				r = x % 10;
   				if (INT_MIN / 10 > temp) return 0;
   				temp = ans * 10;
   				if (INT_MIN - r > temp) return 0;
   				ans = temp + r;
   				x /= 10;
   				temp = ans;	
   	}
   	return ans;
   }
           
如有任何問題,歡迎與我交流

繼續閱讀