這是第二遍讀C++ Primer Plus這本書,對C++的認識有了進一步的瞭解,關於計算機對代碼的編譯過程有了進一步的瞭解,這裏寫出來作爲自己的筆記。
代碼的編譯過程大致分爲以下幾個步驟:預處理-編譯-鏈接-生成。
說下對這句話總得理解:在編寫代碼時,總會有.h和.c文件,實際上編譯的過程是將.c文件轉化爲目標文件(計算機可以識別的文件,一般都以.o文件作爲後綴),進一步在將所有的目標文件進行鏈接形成一個可執行文件。
預處理的過程在淺層上的理解就是執行#等文件,而從實際原理上來說,是將每一個.c文件的代碼的#部分找出來,然後進行預處理的過程:這個過程是將#後邊的內容解析出來,如文件包含#include <iostream> 就是將iostream文件的內容放在.c文件的開頭,經過所有的替換之後,就相當於東風也具備了,就可以真正的解析.c文件了。
在構建代碼的時候,要考慮到每一個.c文件都是一個相對獨立的個體,用到外部的東西,都應該用#預處理語句包含進來。這裏會涉及到自己寫.h文件的幾個注意事項:
(1).自己寫.h文件一定要防止重複包含。可以使用#ifndef #define 或者使用#pragma once等。
(2).儘量不要在.h文件中包含其他文件,而是在對應.c文件中包含需要的文件,這樣可以減少程序的複雜度,更好理解
(3)..h文件一定不可以用來定義變量,只可以聲明,否則就會編譯錯誤
(4)..h文件中儘量不要使用過於複雜的類或者模板作爲參數,如string,就會產生warning,雖然可以關閉warning,但是強迫症表示函數有些不舒服。
然後就可以將文件轉換爲目標文件,接下來的步驟是鏈接的過程,就是將所有的.o目標文件轉化爲一個可執行文件,但是這個過程如果遇到重複定義等的問題就會報錯,或者無法找到對應的依賴庫。所以在涉及的過程中就要注意變量的定義,防止出現錯誤。
在進行鏈接之前,編譯器需要對函數進行適當的處理,這樣鏈接程序才能認識函數,實現真正的鏈接程序的效果,那麼在底層編譯器是如何處理這些函數,使其可以成爲被鏈接程序認識的語言呢?
在C++中,一般講函數轉成_函數名_參數類型名_參數類型名,如int add(int a,double b),會被轉化爲_add_i_d,這種轉化被稱爲C++的語言鏈接性。但是在C語言中並不是這樣操作的,會被轉化爲_add形式,所以兩種是完全不同的編譯形式,但是時長會出現這樣的情況,例如在C++的程序中必須使用C函數庫,如lua的函數庫,所以必須使用C的編譯形式,系統才能正常找到函數,進行正常的鏈接工作。
一般使用如下方式聲明編譯的方式:
extern "C" void add(); //根據C語言的規則
void add(); //根據C++的規則
extern "C++" void add(); //根據C++的規則