跳轉到內容

C++ 程式設計

來自華夏公益教科書,開放的書籍,開放的世界

編譯器

[編輯 | 編輯原始碼]

一個 編譯器 是一個將用一種 計算機語言原始碼)編寫的 計算機程式 翻譯成等效的用計算機的原生 機器語言 編寫的程式的程式。這個翻譯過程,包括幾個不同的步驟,被稱為 編譯。由於編譯器本身就是一個程式,用計算機語言編寫,所以這種情況似乎是一個悖論,類似於 先有雞還是先有蛋 的困境。編譯器可能不是用最終可編譯的語言建立的,而是用之前可用的語言或甚至用機器程式碼建立的。

編譯器的 編譯 輸出是翻譯或 編譯 程式的結果。輸出中最重要的一部分儲存到一個名為 目標檔案 的檔案中,它包含將原始檔轉換為目標檔案的轉換。

注意
某些檔案可能需要建立/用於成功編譯。該資料不是 C++ 語言的一部分,可能是外部程式碼編譯的結果(例如庫)。這可能取決於您使用的特定編譯器(例如,MS Visual Studio 會為專案新增一些額外的檔案),在這種情況下,您應該檢視文件。該資料也可以是需要訪問的特定框架的一部分。請注意,這些構造中的某些構造可能會限制程式碼的可移植性。

然後,如果目標檔案是可執行格式,計算機可以執行(執行)該 編譯 程式的指令。但是,編譯還需要額外的步驟:預處理和連結。

編譯時

[編輯 | 編輯原始碼]

定義編譯器在構建(建立)程式(可執行或不可執行)期間執行的時間和操作(即 編譯時操作)。C++ 語言中“static”的大多數用法與編譯時資訊直接相關。

編譯時執行的操作通常包括 詞法分析語法分析、各種型別的 語義分析(例如,型別檢查、一些 型別轉換模板例項化)以及 程式碼生成

程式語言的定義將指定原始碼必須滿足的編譯時要求才能成功編譯。

編譯時發生在 連結時(將一個或多個編譯檔案的輸出連線在一起)和執行時(程式執行時)之前。在一些程式語言中,可能需要在執行時進行一些編譯和連結。

執行時

執行時執行時間 從程式開始執行的那一刻開始,到程式退出時結束。在這個階段,編譯器無關緊要,沒有控制權。這是關於最佳化的最重要的位置(程式只編譯一次,但執行很多次)和除錯(跟蹤和互動只有在這個階段才能實現)。但執行時也是一些 型別轉換可能發生 的地方,執行時型別資訊 (RTTI) 與此相關。執行時的概念將在相關時再次提及。

詞法分析
[編輯 | 編輯原始碼]

這也被稱為掃描或 標記化。它發生在語法分析之前,並將程式碼轉換為 標記,這些標記是程式實際使用的程式碼部分。原始碼以字元(排列在行上)的形式表達為每個保留關鍵字的特殊標記序列,以及資料型別和識別符號以及值的標記。詞法分析器是編譯器的一部分,它從原始碼中刪除空格和其他不可編譯字元。它使用空格來分隔不同的標記,並忽略空格。

為了簡單說明這個過程

int main()
{
    std::cout << "hello world" << std::endl;
    return 0;
}

根據使用的詞法規則,它可能被 標記化

1 = string "int"
2 = string "main"
3 = opening parenthesis
4 = closing parenthesis
5 = opening brace
6 = string "std"
7 = namespace operator
8 = string "cout"
9 = << operator
10 = string ""hello world""
11 = string "endl"
12 = semicolon
13 = string "return"
14 = number 0
15 = closing brace

因此,對於這個程式,詞法分析器可能會發送類似的東西

1 2 3 4 5 6 7 8 9 10 9 6 7 11 12 13 14 12 15

給下一個將要解析的語法分析器。當它可以處理數值並能夠區分語言語法(例如分號)和所有其他內容時,語法分析器更容易應用語言規則,並且知道每個事物的資料型別。

語法分析
[編輯 | 編輯原始碼]

此步驟(有時也稱為語法檢查)確保程式碼有效,並將按順序組成可執行程式。語法分析器將規則應用於程式碼,檢查以確保每個左括號都有一個對應的右括號,每個宣告都有一個型別,以及該型別存在,以及……語法分析比詞法分析更復雜 =)。

例如

int main()
{
    std::cout << "hello world" << std::endl;
    return 0;
}
  • 語法分析器將首先檢視字串“int”,將其與定義的關鍵字進行比較,並發現它是一個整數型別。
  • 然後,分析器會將下一個標記視為識別符號,並檢查以確保它使用的是有效的識別符號名稱。
  • 然後它將檢視下一個標記。因為它是一個左括號,所以它將“main”視為一個函式,而不是一個變數宣告(如果它找到一個分號)或一個整數變數的初始化(如果它找到一個等號)。
  • 在左括號之後,它將找到一個右括號,這意味著該函式有 0 個引數。
  • 然後它會檢視下一個標記,發現它是一個左大括號,所以它會認為這是函式 main 的實現,而不是 main 的宣告(如果下一個標記是分號的話),即使在 C++ 中不能宣告 main。它可能還會建立一個計數器來跟蹤語句塊的級別,以確保括號成對出現。*之後它會檢視下一個標記,可能不會對其進行任何操作,但然後它會看到 :: 運算子,並檢查 "std" 是否是一個有效的 名稱空間
  • 然後它會看到下一個標記 "cout" 作為 "std" 名稱空間 中識別符號的名稱,並發現它是一個模板。
  • 分析器會看到下一個標記 << 運算子,因此它會檢查 << 運算子是否可以與 cout 一起使用,以及下一個標記是否可以與 << 運算子一起使用。
  • 下一個標記 ""hello world"" 後面的標記也會發生同樣的事情。然後它會再次遇到 "std" 標記,檢視它後面的 :: 運算子標記,並檢查 名稱空間 是否再次存在,然後檢查 "endl" 是否在 名稱空間 中。
  • 然後它會看到分號,所以它會將其視為語句的結束。
  • 接下來它會看到關鍵字 return,然後期望下一個標記是一個整數值,因為 main 返回一個整數,它會找到 0,這是一個整數。
  • 然後下一個符號是分號,所以這是語句的結束。
  • 下一個標記是右大括號,所以這是函式的結束。並且沒有更多標記了,所以如果語法分析器沒有在程式碼中發現任何錯誤,它會將標記傳送給編譯器,以便程式可以被轉換為機器語言。

這只是語法分析的一個簡單檢視,真正的語法分析器並不真正以這種方式工作,但其思想是相同的。

以下是一些語法分析器會查詢的關鍵字,以確保您沒有將它們用作識別符號名稱,或者瞭解您正在定義的變數型別或正在使用的函式,這些函式包含在 C++ 語言中。

編譯速度

[edit | edit source]

有幾個因素決定了編譯的速度,例如

  • 硬體
    • 資源(慢速 CPU、記憶體不足,甚至慢速 HDD 都會有影響)
  • 軟體
    • 編譯器本身,新的總是更好,但可能取決於您希望專案移植到什麼程度。
    • 為程式選擇的方案(物件依賴結構、包含)也會起作用。

經驗表明,如果您遇到編譯速度慢的問題,您嘗試編譯的程式設計很差,花點時間構建自己的程式碼以最大程度地減少更改後的重新編譯。大型專案總是編譯速度更慢。使用預編譯標頭檔案和外部標頭檔案保護。我們將在本書的 最佳化 部分討論減少編譯時間的方法。

哪裡可以獲得編譯器

[edit | edit source]

在選擇編譯器時,您必須考慮您的系統作業系統、個人偏好以及您在使用它時可以獲得的文件。

如果您沒有、不想或不需要在機器上安裝編譯器,可以使用 http://ideone.com(或 http://codepad.org,但您需要更改程式碼以不需要互動式輸入)上的 WEB 免費編譯器。如果您需要,您總是可以在本地獲得一個。

有很多編譯器,甚至更多的 IDE 可用,有些是免費的和開源的。IDE 通常會將所需的編譯器包含在安裝中(GCC 是最常見的)。

GCC 是最成熟、最相容的 C++ 編譯器之一,也稱為 GNU 編譯器集合。它是一套由自由軟體基金會開發的免費編譯器,理查德·斯托曼是主要架構師之一。

網際網路上有許多不同的預編譯 GCC 二進位制檔案;下面列出了一些流行的選擇(以及詳細的安裝步驟)。您可以在 GCC 網站上輕鬆找到有關如何在其他作業系統上執行此操作的資訊。

注意
編譯器通常是用 C 語言實現的(因為它通常是系統語言,在組合語言之上,新的系統會實現它)。GCC 最終在 2005 年 5 月底,獲得綠燈開始將核心程式碼庫遷移到 C++。考慮到這是最常用的編譯器,也是一個開源實現,對於編譯器和語言本身來說,這是一個非常積極的步驟。

IDE(整合開發環境)

[edit | edit source]
GTK2 下的圖形化 Vim

整合開發環境 是一種軟體開發系統,它通常將編輯器、編譯器和偵錯程式整合在一個一起分發的整合包中。有些 IDE 需要使用者自己進行元件整合,而另一些則將 IDE 稱為他們用於程式設計的一組獨立工具。

一個好的 IDE 是一個允許程式設計師使用它來抽象和加速一些更常見任務,同時在閱讀和管理程式碼方面提供一些幫助的 IDE。除了編譯器之外,C++ 標準對不同的實現沒有控制。大多數 IDE 都是面向視覺的,尤其是新的 IDE,它們將提供圖形偵錯程式和其他視覺輔助工具,但有些人仍然喜歡像 VimEmacs 這樣的強大文字編輯器提供的視覺簡潔。

在選擇 IDE 時,請記住,您也在投入時間來精通它的使用。完整性、穩定性和跨作業系統的可移植性將非常重要。

對於 Microsoft Windows,您還有 Microsoft Visual Studio Community(最新版本 2019),目前可以免費獲得,並且包含大多數功能。它包含一個 C++ 編譯器,可以從命令列或提供的 IDE 中使用。

在本書的 附錄 B:外部參考 中,您將找到對可以使用的其他免費編譯器和 IDE 的引用。

在 Windows 上
[edit | edit source]

Cygwin

  1. 轉到 http://www.cygwin.com 並單擊頁面右上角的“立即安裝 Cygwin”按鈕。
  2. 在彈出的視窗中單擊“執行”,然後多次單擊“下一步”,接受所有預設設定。
  3. 當該視窗彈出時,選擇任何下載站點(“ftp.easynet.be”等);按“下一步”,Cygwin 安裝程式應開始下載。
  4. 當“選擇包”窗口出現時,向下滾動到“Devel”標題,並單擊它旁邊的“+”。在現在顯示的包列表中,向下滾動並找到“gcc-c++”包;這是編譯器。單擊“跳過”一詞一次,它應該更改為類似“3.4”之類的數字(版本號),並且“gcc-core”以及現在將要下載的幾個其他必需包旁邊會出現一個“X”。
  5. 單擊“下一步”,編譯器以及 Cygwin 工具應開始下載;這可能需要一段時間。在等待的同時,轉到 http://www.crimsoneditor.com 並下載該免費程式設計師編輯器;它功能強大,但對於初學者來說易於使用。
  6. Cygwin 下載完成後,點選“下一步”等完成安裝,雙擊桌面上的 Cygwin 圖示啟動 Cygwin “命令提示符”。 您的主目錄將自動設定在 Cygwin 資料夾中,現在應該在“C:\cygwin”中(Cygwin 資料夾在某種程度上就像您 Windows 機器上的一個小 Unix/Linux 計算機——當然不是技術上,但把它想象成那樣可能會有所幫助)。
  7. 在 Cygwin 提示符下輸入“g++”並按“回車”; 如果出現“g++: no input files”或類似的資訊,則表示您已成功安裝了 gcc C++ 編譯器到您的計算機上(恭喜——您還剛剛收到您的第一個錯誤資訊!)。

MinGW + DevCpp-IDE

  1. 前往 http://www.bloodshed.net/devcpp.html ,(嚴重過時,上次更新於 2005 年)(http://orwelldevcpp.blogspot.com/) (Updated Branch project) 選擇您想要的版本(最終向下滾動),然後點選相應的下載連結! 對於最新版本,您將被重定向到 http://www.bloodshed.net/dev/devcpp.html
  2. 向下滾動以閱讀許可證,然後到下載連結。 下載包含 Mingw/GCC 的版本。 它比自己組裝要容易得多。 經過短暫的延遲(只有幾天),您將始終獲得與 devcpp IDE 打包的最新版本的 MinGW。 它與手動下載所需模組完全相同。
  3. 您將獲得一個可執行檔案,可以在任何 WinNT 版本的使用者級別下執行。 但是,如果您希望將其設定為所有使用者,則需要管理員許可權。 它將安裝 devcpp 和 mingw 到您想要的資料夾中。
  4. 啟動 IDE 並體驗您的第一個專案!
    您會發現它與 MSVC 大致相似,包括選單和按鈕放置。 當然,如果您熟悉前者,許多方面會有所不同,但只需點選幾下即可讓您的第一個程式執行。
對於 DOS
[編輯 | 編輯原始碼]

DJGPP

  • 前往 Delorie 軟體 並下載 GNU C++ 編譯器和其他必要的工具。 該網站提供了一個 Zip Picker,以幫助您確定需要哪些檔案,該檔案可在主頁面上獲得。
  • 使用 unzip32 或其他提取工具將檔案放置到您選擇的目錄中(例如 C:\DJGPP)。
  • 設定環境變數以配置 DJGPP 進行編譯,方法是將行新增到 autoexec.bat 或自定義批處理檔案中
    set PATH=C:\DJGPP\BIN;%PATH%
    set DJGPP=C:\DJGPP\DJGPP.ENV
  • 如果您執行的是 MS-DOS 或 Windows 3.1,則需要在 config.sys 中新增幾行,如果它們不存在。
    shell=c:\dos\command.com c:\dos /e:2048 /p
    files=40
    fcbs=40,0

注意: DJGPP 下的 GNU C++ 編譯器名為 gpp

對於 Linux
[編輯 | 編輯原始碼]
  • 對於 Gentoo,GCC C++ 是系統核心的一部分(因為 Gentoo 中的所有內容都是編譯的)
  • 對於 Redhat,獲取一個 gcc-c++ RPM,例如使用 Rpmfind,然後使用以下命令安裝(作為 root):rpm -ivh gcc-c++-version-release.arch.rpm
  • 對於 Fedora,使用以下命令安裝 GCC C++ 編譯器(作為 root):dnf install gcc-c++
  • 對於 Mandrake,使用以下命令安裝 GCC C++ 編譯器(作為 root):urpmi gcc-c++
  • 對於 Debian,使用以下命令安裝 GCC C++ 編譯器(作為 root):apt-get install g++
  • 對於 Ubuntu,使用以下命令安裝 GCC C++ 編譯器:sudo apt-get install g++
  • 對於 openSUSE,使用以下命令安裝 GCC C++ 編譯器(作為 root):zypper in gcc-c++
  • 如果您無法成為 root 使用者,請從 [1] 獲取 tarball 並按照其中的說明在您的主目錄中編譯和安裝。
對於 Mac OS X
[編輯 | 編輯原始碼]

Xcode(Apple 的 OSX 和 iOS 的 IDE)v4.1 以上版本使用 Clang [2],它是 GCC 編譯器的免費開源替代方案,與 GCC 大致相容(甚至使用相同的命令列引數)。 IDE 還捆綁了 GCC C++ 編譯器的舊版本。 它可以透過與 Linux 相同的方式從終端呼叫,但也可以在 XCode 的其中一個專案中進行編譯。

注意
Clang 不是 GCC 的唯一替代品,甚至不是唯一的免費替代品。 書籍的 外部連結部分 中包含了一些其他可能性。 Clang 已獲得越來越多的採用,因為它允許更好的程式碼最佳化和內部索引,從而支援 IDE 中更復雜的功能,例如程式碼補全、高亮顯示和其他程式設計師現在越來越依賴的現代功能。 這些在 GCC 上也是可能的,但需要構建和額外的工具,使其速度變慢。 雖然 GCC 仍然是免費開源 C++ 編譯器的預設標準,但 Clang 似乎正在勢頭越來越大。 可用於 Linux(Ubuntu)、FreeBSD、OSX 和 Windows(mingw)的二進位制檔案可以從 http://llvm.org/releases/download.html 下載。


Clipboard

待辦事項
涵蓋為什麼要儘可能避免編譯器擴充套件的章節(一頁),並用於彙總 C++ 程式設計師應對編譯器擴充套件所需的一些有用資訊。

華夏公益教科書