日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 人工智能 > pytorch >内容正文

pytorch

【C语言进阶深度学习记录】十八 条件编译的使用与分析

發(fā)布時(shí)間:2023/12/10 pytorch 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C语言进阶深度学习记录】十八 条件编译的使用与分析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • 1 基本概念
      • 1.1 代碼分析
      • 1.2 通過(guò)命令行定義宏
    • 2 #include 的本質(zhì)
      • 2.1 解決重復(fù)包含頭文件的問(wèn)題
    • 3 條件編譯的應(yīng)用
    • 4 總結(jié)

1 基本概念

  • 條件編譯的行為類似于C語(yǔ)言中的if … else…
  • 條件編譯是預(yù)編譯指示指令,用于控制是否編譯某段代碼

比如下圖的代碼:

  • 上面的 #if、#else、#endif 就是條件編譯的構(gòu)成當(dāng)然,還有其他的樣式,后面會(huì)通過(guò)例子詳細(xì)說(shuō)明。

1.1 代碼分析

如下代碼:

  • 22-1.c
#include <stdio.h>#define C 1 int main(){const char* s;#if(C == 1)s = "This is first printf...\n";#else s = "This is second printf...\n";#endifprintf("%s", s);return 0; }
  • 上述代碼編譯運(yùn)行結(jié)果為:

This is first printf…

上面的代碼,看起來(lái)很簡(jiǎn)單,實(shí)際上,因?yàn)闂l件編譯雖然像if…else 但是它并不像if…else那樣在程序運(yùn)行的時(shí)候進(jìn)行判斷,而是在預(yù)編譯器編譯的時(shí)候就決定了。什么意思呢?可以使用預(yù)編譯指令對(duì)上述代碼進(jìn)行預(yù)編譯(當(dāng)然,為了簡(jiǎn)潔,先將1行和第14行需要使用標(biāo)準(zhǔn)庫(kù)文件的代碼注釋掉)

  • gcc -E 22-1.c -o 22-1.i
  • 生成的預(yù)編譯文件22-1.i 內(nèi)容如下:
# 1 "22-1-lyy.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "22-1-lyy.c"int main(){const char* s;s = "This is first printf...\n";return 0; }
  • 可以看到,在預(yù)編譯階段,就已經(jīng)將條件編譯指令處理完了,預(yù)編譯結(jié)束后,就只剩下,條件編譯中為真的那段代碼。如上面的代碼。所以我們可以總結(jié)出下面幾條規(guī)則:
  • 預(yù)編譯器根據(jù)條件編譯指令有選擇的刪除代碼
  • 預(yù)編譯器不知道代碼分支的存在
  • if … else… 在程序的運(yùn)行期進(jìn)行判斷
  • 條件編譯指令在預(yù)編譯期就進(jìn)行了判斷,并且將條件為真的代碼保留,為假的代碼刪除。
  • 1.2 通過(guò)命令行定義宏

    • 補(bǔ)充一點(diǎn),我們還可以通過(guò)命令行定義宏,而無(wú)需再代碼中定義,如下圖所示:

    如下代碼:

    • 22-2.c
    #include <stdio.h>int main() {const char* s;#ifdef Cs = "This is first printf...\n";#elses = "This is second printf...\n";#endifprintf("%s", s);return 0; }
  • 如果使用下面的方法編譯:
    • gcc 22-2.c -o 22-2.out

    運(yùn)行結(jié)果為:

    This is second printf…

  • 如果使用下面的方法編譯:
    • gcc -DC 22-2.c -o 22-2.out 或者 gcc -DC=1 22-2.c -o 22-2.out

    運(yùn)行結(jié)果為:

    This is first printf…

    我想上面的示例,已經(jīng)足以讓我們學(xué)會(huì)使用命令行定義宏了

    2 #include 的本質(zhì)

    這個(gè)我們已經(jīng)熟悉的不能再熟悉的東西了,包含頭文件,有什么玄機(jī)?

    • #include 的本質(zhì)是將已經(jīng)存在的文件嵌入到當(dāng)前文件中
    • #include 的間接包含,同樣會(huì)產(chǎn)生嵌入文件的操作,這樣會(huì)導(dǎo)致一個(gè)文件包含兩個(gè)相同的頭文件,這會(huì)產(chǎn)生錯(cuò)誤。

    比如下圖的形式,編譯會(huì)出錯(cuò):

    以下面三個(gè)代碼為例,來(lái)說(shuō)明:

    • global.h代碼
    // global.h int global = 10;
    • test.h
    // test.h #include "global.h" const char* NAME = "test.h"; char* hello_world() { return "Hello world!\n"; }
    • 2-3.c
    #include <stdio.h> #include "test.h" #include "global.h"int main() {const char* s = hello_world();int g = global;printf("%s\n", NAME);printf("%d\n", g);return 0; }

    編譯運(yùn)行上述三個(gè)代碼;

    • gcc 22-3.c -o 22-3.out
    • ./22-3.out

    上面錯(cuò)誤的行數(shù)不一樣是因?yàn)槲覀€(gè)人的代碼行數(shù)與上面的不一樣,這個(gè)可以忽略

    • 從上面的錯(cuò)誤可以看出,變量global 重復(fù)定義了。很明顯,我們并沒(méi)有重復(fù)定義。
    • 對(duì)上述代碼進(jìn)行預(yù)編譯(首先將第1、10、11 行注釋掉,方便文件內(nèi)容查看),gcc -E 22-3.c -o 22-3.i 得出的預(yù)編譯文件內(nèi)容如下:
    # 1 "22-3.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "22-3.c"# 1 "test.h" 1# 1 "global.h" 1int global = 10; # 6 "test.h" 2const char* NAME = "test.h"; char* hello_world(){return "Hello world!\n";} # 3 "22-3.c" 2 # 1 "global.h" 1int global = 10; # 4 "22-3.c" 2int main() {const char* s = hello_world();int g = global;return 0; }

    從上面的預(yù)編譯文件可以看出:

  • 11行和23行中,該程序包含了兩次 global.h 這個(gè)頭文件
  • 15行和27行中,該程序定義了兩次global 這個(gè)變量,導(dǎo)致了變量的重復(fù)定義
  • 所以代碼編譯出錯(cuò)。將源代碼test.h中包含的global.h文件注釋掉,重新編譯即可。
  • 2.1 解決重復(fù)包含頭文件的問(wèn)題

    在一個(gè)大型軟件中,重復(fù)包含頭文件是非常普遍的,如果我們一個(gè)一個(gè)的去找,那就會(huì)太浪費(fèi)時(shí)間。

    使用條件編譯,是可以解決該問(wèn)題的。比如將上面的global.h 與test.h改為如下樣式:

    • global.h
    // global.h #ifndef _GLOBAL_H_ #define _GLOBAL_H_ int global = 10;#endif
    • test.h
    // test.h #ifndef _TEST_H_ #define _TEST_H_#include "global.h"const char* NAME = "test.h";char* hello_world(){ return "Hello world!\n";}#endif

    改好上面兩個(gè)文件后,重新編譯運(yùn)行代碼,結(jié)果如下:

    • 上面改變后的global.h與test.h 只是加了個(gè)條件編譯指令,如果某一頭文件被包含過(guò)一次,再要包含它的時(shí)候,由于不符合條件編譯的條件,就不會(huì)有后面的代碼,這樣就避免了一個(gè)頭文件被重復(fù)包含的錯(cuò)誤。(如果不理解,回頭從頭看起,多看兩遍)

    3 條件編譯的應(yīng)用

    條件編譯可以定義軟件產(chǎn)品的發(fā)布版與調(diào)試版

    可以在代碼中使用條件編譯來(lái)定義需要調(diào)試的代碼,當(dāng)整個(gè)軟件產(chǎn)品都調(diào)試通過(guò)最終需要發(fā)布的時(shí)候,可以直接去掉相關(guān)的宏定義(或者直接使用命令行的時(shí)候,不定義調(diào)試需要的宏即可),就可以使得代碼在編譯的時(shí)候,直接刪除調(diào)試部分的代碼,而無(wú)需自己動(dòng)手刪除。

    本部分就不寫(xiě)實(shí)驗(yàn)了。

    4 總結(jié)

    • 條件編譯可以使得我們按照不同的條件編譯不同的代碼片段,因而可以產(chǎn)生不同的目標(biāo)代碼
    • 通過(guò)編譯器命令行,可以定義預(yù)處理器使用的宏
    • 條件編譯,可以避免重復(fù)包含同一個(gè)頭文件多次
    • 條件編譯可以定義軟件產(chǎn)品的發(fā)布版和調(diào)試版

    總結(jié)

    以上是生活随笔為你收集整理的【C语言进阶深度学习记录】十八 条件编译的使用与分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。