最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊

第 14 講:運(yùn)算符(六):溢出校驗(yàn)運(yùn)算符

2021-03-29 10:49 作者:SunnieShine  | 我要投稿

Part 1 溢出和數(shù)據(jù)處理

1-1 溢出的概念

C# 里出現(xiàn)了一種新的處理過程,叫做溢出校驗(yàn)(Overflow Checking)。在數(shù)據(jù)類型的內(nèi)容里,我們說到,任何一種數(shù)據(jù)類型都是具有有限的存儲(chǔ)空間的。既然空間有限,那么自然數(shù)據(jù)存儲(chǔ)就是有限的。比如說 byte,最大只能到 255。如果我們有這樣的一種情況:

我們嘗試對 a 繼續(xù)增大一個(gè)單位,會(huì)如何呢?這個(gè)情況被稱為溢出(Overflow)。但是很遺憾的是,在 C 語言里,數(shù)據(jù)溢出是未定義行為(Undefined Behavior,簡稱 UB)。未定義行為這個(gè)概念不好理解,不過說白了就是,不同的編譯器對這句話的理解不同。具象化示例:比如說有三個(gè)人,它們看這句話會(huì)產(chǎn)生三種不同的意思。那么這句話就稱為未定義的,它執(zhí)行的行為就稱為未定義行為。

那么,說這個(gè)溢出是未定義行為,是什么意思呢?就是說,有可能這個(gè)編譯器會(huì)對溢出情況這么做,但別的編譯器可能那么做,總之做法不同。既然沒有統(tǒng)一的處理模式,那么代碼上就是不嚴(yán)謹(jǐn)?shù)?。因此,C# 將這種溢出完善了。

在 C# 里,我們有兩種處理模式:

  • 沒有溢出校驗(yàn):將數(shù)值從這個(gè)數(shù)據(jù)類型的最大值直接改成這個(gè)數(shù)據(jù)的最小值,就認(rèn)為它增大了一個(gè)單位;

  • 啟用溢出校驗(yàn):當(dāng)溢出的時(shí)候,直接產(chǎn)生一個(gè)運(yùn)行錯(cuò)誤。

大多數(shù)時(shí)候,直接產(chǎn)生運(yùn)行錯(cuò)誤是沒必要的,因?yàn)槲覀兌加貌坏竭@種“邊界處理”。但 C# 仍舊提供了這種行為。比如說我寫了一個(gè)計(jì)算器的程序。如果數(shù)據(jù)在計(jì)算的時(shí)候超出了數(shù)據(jù)能表示的范圍,我們肯定希望用戶可以看到“數(shù)據(jù)超出計(jì)算范圍”的信息。如果選擇前者處理模型的話,由于它不會(huì)產(chǎn)生錯(cuò)誤信息,因此我們根本不可能從代碼層面實(shí)現(xiàn)“讓用戶看到運(yùn)算超出范圍”的結(jié)果。在這種情況下,我們可能會(huì)考慮選擇后者。

1-2 沒有溢出校驗(yàn)的處理,為什么會(huì)從最大值改成最小值?

C# 采用了一種容易電腦處理的機(jī)制。我們拿 byte 類型舉例。byte 只需要 8 個(gè)比特位,如果是 255 的話,這個(gè)數(shù)值一定是 1111 1111。當(dāng)給這個(gè)數(shù)值增大一個(gè)單位的時(shí)候,數(shù)字會(huì)變成 1 0000 0000。但是很顯然,byte 類型只能使用 8 個(gè)比特位,那么超出來的最高位的 1 就必須得舍棄。因此這個(gè)數(shù)值就變成了 0000 0000;而這個(gè)數(shù)字就是 0。這不就是從最大改成最小了嘛。

所以,對于一個(gè)整數(shù)類型來說,如果對這個(gè)數(shù)據(jù)類型的最大值再增大一個(gè)單位,就會(huì)將這個(gè)數(shù)字變成這個(gè)數(shù)據(jù)類型的最小值;反之的話,如果這個(gè)數(shù)字是這個(gè)數(shù)據(jù)類型的最小值,那么減小一個(gè)單位,自然就變成最大值了:因?yàn)闇p 1 的話不夠減,就會(huì)瘋狂從高位借位,然后就全部比特位都得借,因此就變成了最大值了。

在說完前面的內(nèi)容之后,下面我們來說一下如何使用這個(gè)溢出校驗(yàn)的功能。

Part 2 啟用溢出校驗(yàn)

啟用溢出校驗(yàn)是通過項(xiàng)目配置文件來啟用的。為了學(xué)習(xí)簡單,我們使用較為簡單的配置方式:使用界面。

首先,我們找到解決方案資源管理器,單擊項(xiàng)目。

在點(diǎn)擊之后,會(huì)彈出設(shè)置頁面。當(dāng)然,你依然可以在選中項(xiàng)目后,點(diǎn)擊右鍵,選擇“Properties”(屬性),進(jìn)入設(shè)置頁面。

在進(jìn)入配置頁面后,找到“Build”(生成)選項(xiàng)卡下,右下角的“Advanced...”。

最后選擇啟用溢出檢查就可以了。

這樣就完成了啟用溢出校驗(yàn)。

順帶一提。如果沒有這里的這些個(gè)步驟的話,整個(gè)項(xiàng)目里的代碼是不會(huì)檢查溢出的。換句話說,即使產(chǎn)生了溢出,也不會(huì)產(chǎn)生錯(cuò)誤,而是使用默認(rèn)的計(jì)算邏輯(就前面那個(gè),最大變最小,最小變最大的那個(gè));如果啟用了的話,整個(gè)項(xiàng)目的所有加減乘除模這些會(huì)改動(dòng)變動(dòng)數(shù)據(jù)數(shù)值的過程都會(huì)在運(yùn)算結(jié)果的過程期間校驗(yàn)是不是會(huì)溢出。如果溢出就自動(dòng)產(chǎn)生錯(cuò)誤,讓程序崩潰。

當(dāng)然,產(chǎn)生這個(gè)錯(cuò)誤讓程序崩潰的過程是可以在將來得到處理的,換句話說,我們以后會(huì)學(xué)到一種處理邏輯,會(huì)“捕獲”這種錯(cuò)誤信息,然后避免程序崩潰,并在這種錯(cuò)誤發(fā)生后,給用戶提示對應(yīng)的錯(cuò)誤信息,防止程序閃退。這種過程現(xiàn)在我們說不到,因此我們這里先賣個(gè)關(guān)子。

Part 3 checkedunchecked 關(guān)鍵字

下面我們的重頭戲就來了。我們使用 checked 關(guān)鍵字或 unchecked 關(guān)鍵字專門用來控制代碼是否需要校驗(yàn)溢出。前文我們介紹了如何配置項(xiàng)目啟用校驗(yàn)溢出的過程,這里我們來實(shí)際使用一下。

先來說一下功能:

  • checked 關(guān)鍵字:用于一個(gè)表達(dá)式或一個(gè)代碼塊,表示這個(gè)表達(dá)式或者代碼段落都啟用溢出檢查。如果前文我們配置溢出的過程已經(jīng)完成,那么項(xiàng)目里面就不必使用這個(gè)關(guān)鍵字;

  • unchecked 關(guān)鍵字:用于一個(gè)表達(dá)式或一個(gè)代碼塊,表示這個(gè)表達(dá)式或代碼段落不啟用溢出檢查。如果前文我們配置溢出的過程沒有做的話,那么項(xiàng)目默認(rèn)就是不檢查的,因此我們不用使用這個(gè)關(guān)鍵字。

我們先來試試寫這么一段代碼:

或者,如果覺得這么寫很丑,你可以這么寫:

這兩種寫法都是沒有問題的。前者這樣寫的話,大括號(hào)里面的部分,只要參與運(yùn)算的地方,都會(huì)檢查溢出;而后面這種,就只對 ++a 檢查是否溢出了。當(dāng)然,實(shí)際上我們可以看到,就算寫成前面那樣,我們也知道里面就只有 ++a 需要校驗(yàn)是否溢出,因此這兩個(gè)寫法是等價(jià)的。

當(dāng)然,如果你配置了項(xiàng)目溢出檢查的話,checked 是可以不用的。這一點(diǎn)前面已經(jīng)說過了。

如果我們嘗試運(yùn)行程序。我們確實(shí)看到了程序崩潰,并產(chǎn)生了一個(gè)錯(cuò)誤:

如果不檢查溢出,我們可以使用 unchecked 關(guān)鍵字來避免檢查。

這樣的話,你就可以得到 0 這個(gè)輸出結(jié)果,并且沒有錯(cuò)誤信息。

Part 4 總結(jié)

本節(jié)內(nèi)容我們學(xué)習(xí)到了 checkedunchecked 關(guān)鍵字的用法。用來標(biāo)記一個(gè)表達(dá)式(或一個(gè)代碼段),來表示這個(gè)表達(dá)式(或代碼段)是否啟用溢出檢查。checked 是啟用,而 unchecked 則是不啟用。

說句實(shí)話,初學(xué)沒有必要搞很清楚,能懂個(gè)大概就可以了。


第 14 講:運(yùn)算符(六):溢出校驗(yàn)運(yùn)算符的評論 (共 條)

分享到微博請遵守國家法律
改则县| 阿克苏市| 通化市| 四子王旗| 远安县| 通山县| 许昌市| 光泽县| 木兰县| 疏勒县| 小金县| 伊宁县| 康保县| 德阳市| 曲水县| 普陀区| 娄底市| 万山特区| 潼南县| 鄱阳县| 昭通市| 南京市| 凤台县| 新沂市| 当涂县| 永春县| 海阳市| 金华市| 北碚区| 唐海县| 元阳县| 湖口县| 瓮安县| 环江| 南郑县| 普兰店市| 阿克陶县| 温州市| 汝南县| 遂宁市| 濮阳市|