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

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

第 28 講:預處理指令

2021-04-27 09:52 作者:SunnieShine  | 我要投稿

預處理指令(Preprocessor),是在程序編譯期間,特別告訴編譯器一些特殊行為的指令。這些指令一定是以井號開頭,且以單行作為單位書寫,因此預處理指令也不需要添加分號結(jié)尾。

預處理指令可以被劃分為如下幾類:

  • 條件編譯指令:#if、#endif#else、#elif、#define、#undef

  • 引發(fā)警告和錯誤指令:#warning、#error

  • 行號指示指令:#line

  • 代碼折疊展開指令:#region、#endregion

  • 消除警告信息指令:#pragma warning

預處理指令的內(nèi)容其實并不多。雖然也分成很多類,但是介紹其實并不是很多,因此打算將它們?nèi)繉懺谶@一篇文章里。下面我們來看看它們的用法。

實際上,還存在一些別的預處理指令,例如 #pragma checksum。但是這個玩意兒對于初學來說,用處非常小,它一般是提供給“代碼生成代碼”過程所需,檢查文件是否有變動。

Part 1 條件編譯

1-1 條件編譯的基本用法

條件編譯(Conditional Compilation)是針對于編程環(huán)境來制定的一種特殊編譯規(guī)則。它不能通過代碼來實現(xiàn),而是通過某一個特征符號來代表當前環(huán)境是如何的。舉個例子,C 語言里的 int 的大小隨著機器的情況,而產(chǎn)生變化。條件編譯剛好可以通過設置一個符號來表達這樣的情況。當用戶在使用程序代碼的時候,如果這個環(huán)境不是這樣的,我們只需要刪除符號就可以達到切換編譯模式的效果。其中,我們使用的、用來區(qū)分不同環(huán)境的這個符號叫做條件編譯符號(Conditional Compilation Symbol)。

下面我們來詳細解釋一下條件編譯的過程。我們之前使用過指針,來完成對底層的兼容。但是很遺憾的是,C 語言的 int 和 C# 的 int 貌似并不能夠直接劃等號。C 語言的 int 是不定長的,因為它隨著系統(tǒng)的位數(shù)有不同的情況;而 C# 里,int 是固定大小。那么,我們不得不在 C# 里指定大小,避免程序的崩潰。

比如這樣的函數(shù)。在導入的時候,int*int 都必須要指定長度,因此,我們需要借助 MarshalAs 特性指定。

int* 則不必指定,因為它的類型是指針。指針類型的長度則和 C 里是一樣的。這樣還不夠。因為 int 大小是沒有指定的,因此我們這里需要借助一個操作了。

我們在 int length 的周圍添加這樣一段代碼,使得整個函數(shù)的聲明改成這樣:

雖說這么寫很丑陋,但是我們這里改動了一些地方。首先,我們使用 #if TARGET_64BITS、#else#endif 包裝了整個參數(shù);而且我們還寫上了兩個截然不同的“方案”,一個是用的 long,而另外一個則是用的 int 類型。這個作用是什么呢?用戶自己是知道你電腦是什么系統(tǒng)、什么位數(shù)的。如果你是 64 位,那么你可以去配置一個叫做 TARGET_64BITS 的符號到項目配置里,然后,C# 自動就會認為 TARGET_64BITS 這個符號存在,那么 #if TARGET_64BITS#else 之間的這段代碼就會得到編譯,而 #else#endif 之間的部分就在 C# 編譯器編譯代碼的時候忽略掉了。

我們在項目配置菜單里找到“Conditional compilation symbols”(條件編譯符號),然后填入 TARGET_64BITS,保存后關(guān)閉。

接著你就可以在你的代碼里,條件編譯的部分,代碼會有著色,但是不編譯的部分,就不會有著色(是灰色的)。

那么這個就稱為條件編譯:我們可以通過自行的配置,將代碼傳給所有人使用的時候,按自己的需求去更替和修改條件編譯符號,然后達到編譯不同的代碼的效果。

當然了,你可能會問我,這些符號是隨便寫的嗎?如果是的話,我怎么知道代碼里用到了什么符號呢?這個問題其實解釋起來很簡單:這個是寫代碼的這個人必須給出來的。你如果要用,那么就可以參考符號的用途,來配置或取消配置這個符號。

1-2 臨時配置編譯符號

條件編譯符號的靈活之處在于它并不一定非得在項目配置菜單里,我們完全可以將符號寫在代碼里,然后提供用戶到底是否是用,還是不用。

我們使用 #define 指令來完成。我們在代碼文件的最開頭添加 #define TARGET_64BITS 來啟用這個符號。

這樣也可以。你甚至可以不用去配置菜單里添加符號,就可以做到。但是前提是,這個符號在 #define 指令的用法下,僅對這一個文件有效。

當然了,你也可以用 #undef 來手動取消對某個符號的啟用。假設你配置了這個符號,你可以使用 #undef 符號名 的格式來取消符號的定義。

1-3 多條件編譯符號的判斷

因為 C 語言的 int 類型隨系統(tǒng)位數(shù)變化而變更大小,而系統(tǒng)位數(shù)還可能是 16 位,所以我們可以這么去操作那段代碼:

我們使用 #elif 指令,可以對前文的條件編譯符號不存在的時候,繼續(xù)判斷另外的符號,這相當于 else-if 組合的條件判斷。

elif 是 else 和 if 兩個單詞的拼接。

Part 2 引發(fā)自定義警告和錯誤

有些時候我們可能需要一點必要的手段來提供給用戶,不要隨意和濫用編譯符號。比如前面的例子里,如果有些用戶故意三個符號都不配置的話,那么這個參數(shù)就留空了。那么前面的參數(shù)最后跟了一個逗號,這必然會產(chǎn)生很嚴重的錯誤。

我們可以這樣。如果三個符號都不配置,我們就在最后一個代碼段落里添加一個 #error 指令,來提供給用戶。

這里的 #error You should specify one symbol in 'TARGET_16BITS', 'TARGET_32BITS' and 'TARGET_64BITS'. 看起來很長,實際上后面的文字是我們自定義的,這表示錯誤信息。當如果不配置上面的三個符號的話,第 8 行自動會產(chǎn)生一個編譯器錯誤,告知用戶“你不能這么用”。

那前面逗號的編譯錯誤呢?沒事,用戶可能會因為別的原因,刪掉那個逗號來避免編譯錯誤,但這是很危險的行為;所以單獨給它設置一條錯誤信息,可以提供給用戶,告訴用戶你不可以這么用。

在實際代碼編譯的時候,因為你正常的配置符號,因此前面三條代碼會挨個判斷,#error 指令完全碰不著。因此,你也不用擔心,這段代碼是否會永久遇到這個編譯錯誤指令。

Part 3 人為變動行號和文件信息

我們簡單說一下就可以了。這個符號對入門來說,也沒啥大用。#line 指令表示,我們從添加這個指令開始,這一行的編號就是指定的數(shù)值了。

如果我們試著這么寫代碼的話,假如我們沒寫 using System; 的話,顯然 Console 就不知道在哪里了,于是編譯器就會產(chǎn)生錯誤信息:找不到 Console。

不過,你查看詳細錯誤信息的時候,在最后你會發(fā)現(xiàn),行號改成 300 了。

這個就是這個符號的用法。我們可以指定錯誤編號在哪里,來故意告知用戶所在位置是一些特殊位置。你甚至可修改文件名稱:

然后,你在查看詳情的時候:

這個 #line 指令就是這個用法。

Part 4 給代碼增加額外的折疊塊

如果代碼非常復雜,我們可能會用到 #region#endregion 指令。#region#endregion 指令是成對出現(xiàn)的,和 #if 以及 #endif 是一樣的,都得成對出現(xiàn)。

舉個例子,我們用上之前的求質(zhì)數(shù)的代碼。我們在三大段代碼之間分別加上 #region#endregion 指令。

#region 指令后可以添加額外的補充說明文字。然后你就會發(fā)現(xiàn),你的代碼頁面的左邊,多了一個加減號。點擊這個符號,這段代碼就折疊起來了。

這個指令就是這么用的。我們可以人為指定代碼塊,然后給它寫上文字;到時候,代碼就可以通過 VS 提供的功能進行代碼的折疊;另外,折疊之后,那個我們寫在 #region 指令后面的文字是可以在折疊的時候呈現(xiàn)出來的。當然了,這個文字是可以不寫的。

Part 5 總結(jié)

總的來說,預處理指令并不是很重要,但是對一些代碼起著非常重要的作用。如果沒有它們,我們可能無法做到一些行為;這些行為可能就是為了補足和完善代碼書寫過程。


第 28 講:預處理指令的評論 (共 條)

分享到微博請遵守國家法律
吉木乃县| 南开区| 新郑市| 枣庄市| 萍乡市| 宁阳县| 扎兰屯市| 武胜县| 驻马店市| 汾西县| 大兴区| 铜川市| 北辰区| 鸡东县| 石城县| 防城港市| 高淳县| 那曲县| 连山| 莎车县| 青浦区| 黄大仙区| 玛多县| 承德市| 滦南县| 富锦市| 怀来县| 新巴尔虎左旗| 神池县| 梁河县| 沙田区| 民县| 柳江县| 资源县| 宜阳县| 丰顺县| 宣武区| 马鞍山市| 石泉县| 连南| 苍南县|