上溢後,結果為什麼可以用 (原值%對應數據類型最大值) 求出?
12-31
有點不理解,求解答。
uint16_t value; // &
value = 100000;
「理應」發生什麼:
首先是賦值:整型間的賦值屬於「簡單賦值」,簡單賦值的規則是「將右側的值轉換為左側的類型,然後替換左側的對象」。
其次是右側「100000」的類型:沒有後綴的十進位數值常量的類型是 int、long、long long 中第一個能夠表示這個值的類型。是那個得看具體的系統,反正不是 uint16_t 就是了。
最後是類型轉換,C 語言標準中描述的規則是這樣的:- 如果新類型可以表示原值,直接保留該值;
- 否則,如果新類型是無符號的,則將原值不斷加上後者減去「新類型的最大值加 1」,直到可以被新類型表示為止;
- 否則,如果新類型是有符號的,由具體實現覺得其行為。
代入此處可以看到
- 100000 無法被 uint16_t 表示,因為表示範圍為 [0, 65535];
- 100000 大於 65535,於是按照規則減去 65535 + 1 得到 34464,可以被 uint64_t 表示,於是得到最終的值,賦予 value。
---
那麼該如何理解題目里的說法呢?回顧小學數學,「餘數」是什麼?編譯器對其二進位表示截取低 16 位,相當於對 65536 求余,得到 34464
當兩個整數相除的結果不能以整數商表示時,餘數便是其「余留下的量」。
回顧小學數學,「除法」是什麼?
所以「X 對 65536 求余」換句話說就是重複的減法
將 X 不斷減去 65536,直到剩下的值在 [0, 65535] 的範圍內
這和上面提到的標準里所說的
將原值不斷加上或者減去「新類型的最大值加 1」,直到可以被新類型表示為止
是一樣的。
---
至於為什麼「對其二進位表示截取低 16 位」相當於「對 65536 求余」:
如果把數 X 的低 16 位記為 L,其餘高位記為 H,那麼可以得到:
「截取低 16 位」後則為:
你看,還是「將 X 不斷減去 65536」,而且是有多少個就減多少個……推薦閱讀:
※在Visual Studio開發c++程序時,怎樣使用和管理第三方的開源庫?
※C++項目怎麼適用不同的linux系統?
※請問float的最大值是怎麼來的?
※寫程序時中間變數用cnm,是什麼心態?
※這一段 C++ 代碼有什麼樣的問題?