函數,從編輯到編譯 (上)

来源:https://www.cnblogs.com/tobe98/archive/2019/09/21/11564536.html
-Advertisement-
Play Games

0. 序 我從一生下來就呆在這個昏暗的地方。 我不明白為什麼程式員這麼喜歡 Dark Mode,Brighten Mode 才是我的最愛。聽說最近連 iphone 都開始支持 Dark Mode 了,沒話講。。。說好的絕不妥協呢? 我周圍是熙熙攘攘的函數群,穿插著變數聲明和巨集定義。 在我們這裡,函數 ...


0. 序

我從一生下來就呆在這個昏暗的地方。

我不明白為什麼程式員這麼喜歡 Dark Mode,Brighten Mode 才是我的最愛。聽說最近連 iphone 都開始支持 Dark Mode 了,沒話講。。。說好的絕不妥協呢?

我周圍是熙熙攘攘的函數群,穿插著變數聲明和巨集定義。

在我們這裡,函數是一等公民。

當然,不光在 C++,在面向過程的 C 語言、面向對象的 Java ,尤其是在那些函數式編程的語言里,我們都扮演著舉足輕重的角色。

能力越大,責任越大。我和一群函數伙伴們就負責維護著程式的功能。每個函數的一小步,合起來就是功能模塊的一大步。

作為一門靜態編譯型語言,我們不像那些解釋語言一樣,寫完就能直接運行,而是要先經過編譯這一道坎,成為機器語言,才能夠運行在我們賴以生存的機器上。

這道坎不是那麼好過的,再頂尖的程式員,也會在這上面栽跟頭。

放在往常,雖然程式偶爾會出 bug ,但大家齊心協力,可謂蟲(bug)擋殺蟲,過五關斬六將,整個程式也稱得上是井井有條。

但這次,我們遇到了大問題。

1. 預編譯

今天的一切看起來都很平凡,至少我是這麼認為的。

屏幕外的程式員像平常一樣敲著代碼,我們像平常迎接著新函數的到來,像平常一樣嬉笑怒罵,像平常一樣期待著預編譯進程的到來。

預編譯進程是整個編譯進程的先鋒。

像往常一樣,我們從磁碟出發,沿著匯流排來到了記憶體。這裡就是進程的工作車間。

預編譯進程第一步會 刪除所有 #define,展開巨集定義。處理條件預編譯指令。

#define WINDOWS
#define BUFSIZE 1024
#define DEPTH 4
#define DECODE "utf-8"
...

上面的就是巨集定義,每次我們都要在預編譯進程的指揮下,把語句里出現的巨集替換成對應的值。

這一步其實本來不需要我們乾的,程式員怕麻煩,想要做到“一處修改,處處更改”,就發明瞭巨集定義,讓編譯器來乾這些“臟活累活”。

處理條件預編譯指令就有點不一樣了:

//windows or linux
#ifdef WINDOWS
<experssion1>
#else
<experssion2>
#endif

如果巨集定義有這個 WINDOWS,就只留下 <experssion1>,沒有的話就留 <experssion2> 。說白了,就是個預編譯階段能執行的 if... else ... 語句。上面的語句一處理,就變成了:

<experssion1>

對,註釋也會被刪除。

可憐那些註釋,這一輩子都不曾領略 CPU 里的風景。

第二步是處理 #include預編譯指令。

這一步就比上面的複雜多了。用專業的話來說,處理 “#include ”預編譯指令,就是將被包含的文件插入到該預編譯指令的位置。這個過程是遞歸進行的,也就是說被包含的文件可能還包含其他文件。

#include "config.h"
<expressions>

別看他們現在就只有短短兩句,等把 config.h文件內容複製過來,信息量一下子就大了。

#ifndef _CONFIG_H_
#define _CONFIG_H_

#define VERSION "1.0.0"
#define MODE 1
...
...
#endif

<expressions>

補充一句,這個 .h 尾碼的家伙,叫頭文件。他是我們與其他文件的函數公民的溝通渠道。

頭文件這個家伙和源文件不太一樣,他是包含功能函數、數據介面聲明的載體文件,主要用於保存程式的聲明。也就是說,頭文件里是沒有函數的——我們曾多次試圖占領頭文件的領地,但都沒有成功——都是因為程式員的約束。

每個頭文件都會帶有一組條件預編譯語句,用來防止自己被多次編譯。

至於怎麼做到的,這太簡單了,我不說你也能想出來。

聽說有的編譯器還支持 #pragma once ,添在頭文件第一行就能做到相同的事情。可惜我們的編譯器有點舊,不相容他們。

最後這步就比較快了,添加行號和文件名標識

走到這裡,我們已經得到了編譯器調試的需要的行號信息,如果編譯到哪一步出錯,或者出現 warning 這樣的警告,就能把行號顯示出來,方便程式員及時發現問題源頭。

今天的預編譯比我想象中要快一點,可能這次沒什麼進程跟我們搶 CPU 資源吧。

預編譯階段結束,# 的數量大大減少,僅剩下幾個 #pragma 指令留在這裡。

和其他巨集定義指令不一樣的是,#pragma 是能夠跟編譯器平起平坐的存在,預編譯進程見了都得避讓三分。

#pragma  warning( disable: 4507 34; once: 4385; error: 164 )

像這條指令,就是專門給編譯器看的,意思是 ‘不顯示4507和34號警告信息 ,4385號警告信息僅報告一次,把164號警告信息作為一個錯誤’ 。可以說,她是程式員和編譯器之間的信鴿。

對於我來說,預編譯階段是比較輕鬆的,最複雜也只是處理條件預編譯指令——刪除幾行代碼罷了。

未完待續

如果大家對文章有什麼看法和意見,歡迎提出來~


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 目的:寫給自己看的,不如其他大神全,以後慢慢修修改改 一:如何判斷數據是否垃圾數據 1.引用計數法 當創建一個對象時,為此對象分配一個引用計數器。當有其他對象引用這個對象時,計數器就+1。當引用失效了,計數器-1。 當一個對象的引用計數器=0時,此對象就可以被回收。 優點:原理簡單,實現方便。 缺點 ...
  • AJAX框架Day1 1、Ajax引言 a) 概念 Asynchronous Javascript And XML (非同步請求 javaScript And XML) b) 傳統的請求 2、非同步請求的開發 a) 非同步請求對象的創建 javascript: XmlHttpRequest對象 xhr C ...
  • 本周的 上分享了一篇小文章,它裡面提到的冷知識很有意思,我稍作補充,分享給大家。 它提到的部分問題,讀者們可以先思考下: 若兩個元組相等,即 a==b 且 a is b,那麼相同索引的元素(如 a[0] 、b[0])是否必然相等呢? 若兩個對象的 hash 結果相等,即 hash(a) == has ...
  • JDK(Java Development Kit) JDK顧名思義就是Java開發工具包,是Sun Microsystems針對Java開發員的產品,是Java程式員通過Java語言編寫程式所需的開發工具包,JDK包含了JRE,同時還包含了編譯Java源碼的編輯器Javac,還包含了很多Java程式 ...
  • 什麼是 PHP 擴展 通俗說,PHP 擴展是增強 PHP 語言功能的插件。PHP 提供了編程語言的語法,比如分支、迴圈、函數、類等,這些是 PHP 本身所提供的。在某些情況下需要在 PHP 語言的基礎上進行擴展,那麼就需要通過 PHP 底層提供的數據結構和介面來開發 PHP 擴展,從而來補充或擴展 ...
  • 聲明 :本博客僅僅是一個初學者的學習記錄、心得總結,其中肯定有許多錯誤,不具有參考價值,歡迎大佬指正,謝謝!想和我交流、一起學習、一起進步的朋友可以加我微信Liu__66666666 這是簡單學習一遍之後的記錄,後期還會修改。 一、學習內容 1. "jvm簡介" 2. 記憶體模型 3. 垃圾回收機制 ...
  • 恢復內容開始 目錄 1. 分支結構 1.1 初步介紹 1.2 使用案例 1.3 練習 2.迴圈結構 1.1 初步介紹 1.2 使用案例 目錄 1. 分支結構 1.1 初步介紹 1.2 使用案例 1.3 練習 2.迴圈結構 1.1 初步介紹 1.2 使用案例 1. 分支結構 1.1 初步介紹 1.2 ...
  • ZooKeeper技術的極少以及ZooKeeper集群的搭建 ...
一周排行
    -Advertisement-
    Play Games
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...
  • 目錄前言PostgreSql安裝測試額外Nuget安裝Person.cs模擬運行Navicate連postgresql解決方案Garnet為什麼要選擇Garnet而不是RedisRedis不再開源Windows版的Redis是由微軟維護的Windows Redis版本老舊,後續可能不再更新Garne ...
  • C#TMS系統代碼-聯表報表學習 領導被裁了之後很快就有人上任了,幾乎是無縫銜接,很難讓我不想到這早就決定好了。我的職責沒有任何變化。感受下來這個系統封裝程度很高,我只要會調用方法就行。這個系統交付之後不會有太多問題,更多應該是做小需求,有大的開發任務應該也是第二期的事,嗯?怎麼感覺我變成運維了?而 ...
  • 我在隨筆《EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)》中介紹了一些基本的EAV模型設計知識和基於Winform場景下低代碼(或者說無代碼)的一些實現思路,在本篇隨筆中,我們來分析一下這種針對通用業務,且只需定義就能構建業務模塊存儲和界面的解決方案,其中的數據查詢處理的操作。 ...
  • 對某個遠程伺服器啟用和設置NTP服務(Windows系統) 打開註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer 將 Enabled 的值設置為 1,這將啟用NTP伺服器功 ...
  • title: Django信號與擴展:深入理解與實踐 date: 2024/5/15 22:40:52 updated: 2024/5/15 22:40:52 categories: 後端開發 tags: Django 信號 松耦合 觀察者 擴展 安全 性能 第一部分:Django信號基礎 Djan ...
  • 使用xadmin2遇到的問題&解決 環境配置: 使用的模塊版本: 關聯的包 Django 3.2.15 mysqlclient 2.2.4 xadmin 2.0.1 django-crispy-forms >= 1.6.0 django-import-export >= 0.5.1 django-r ...
  • 今天我打算整點兒不一樣的內容,通過之前學習的TransformerMap和LazyMap鏈,想搞點不一樣的,所以我關註了另外一條鏈DefaultedMap鏈,主要調用鏈為: 調用鏈詳細描述: ObjectInputStream.readObject() DefaultedMap.readObject ...
  • 後端應用級開發者該如何擁抱 AI GC?就是在這樣的一個大的浪潮下,我們的傳統的應用級開發者。我們該如何選擇職業或者是如何去快速轉型,跟上這樣的一個行業的一個浪潮? 0 AI金字塔模型 越往上它的整個難度就是職業機會也好,或者說是整個的這個運作也好,它的難度會越大,然後越往下機會就會越多,所以這是一 ...
  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。 @Autowired預設按照類型自動裝配,而@Resource預設按照名稱自動裝配。 @Autowired支持@Qualifier註解來指定裝配哪一個具有相同類型的bean,而@Resourc... ...