Re: [問題] 關於C++ compiler的一些問題

看板C_and_CPP (C/C++)作者 (萬年好人)時間18年前 (2006/03/25 17:59), 編輯推噓1(100)
留言1則, 1人參與, 最新討論串1/1
※ 引述《kicksmile (aa)》之銘言: : //class.h檔 : class A{ : public: : void func(); : private: : int x; : }; : //class.cpp檔 : #include "class.h" : void A::func() : { : x=x+1; : } : //main.cpp檔 : #include "class.h" : int main(){ : A a1; : a1.func(); : return 0; : } : 我想請教一下compiler在產生執行檔的過程中都在做些什麼 : 還是有什麼網站有教這些常識謝謝 你是讀什麼的呢?如果是資訊相關科系,有一門課叫做compiler,可以去聽聽看。 compiler主要把原始程式作剖析(parsing),檢查語彙(lexical),檢查語法(syntax)及 檢查語義(semantic),中間的運作過程,細節很多。你也可以去wikipedia找看看。 檢查完後,會替中間碼優化,最後再輸出對應的機械碼。 至於C Compiler的運作,主要是先作preprocessing(處理巨集代換),再作compile,產生 目的碼。有了目的碼後,再利用連結器把不同部份連結,產生執行檔。 : <compile的過程中> : 1.因為class.cpp main.cpp都只include class.h : 所以是不是main.cpp裡在compile的過程中看不到class.cpp裡的func計算過程? compile的過程並不執行程式碼。每一個cpp都只是獨立編譯,再連結。你這句話語焉不詳 。就編譯器而言,它只看得到目前的原始檔,所以它不會管其它的檔案內怎麼寫。但, 就如同我之前講的,不參與計算。 : 2.那我在compile class.cpp時,compiler 是不是只是在做class.h 跟class.cpp的 : pattern 跟type (class裡的function argument, return type)檢查,然後產生class.obj? : 相對的,compile main.cpp 也只是對main.cpp跟class.h做pattern跟type的檢查 : 然後產生main.obj? 對。 : 3.如果是的話,那compiler是在什麼時候才讓main.cpp裡的a1.func()去連結到 : class.cpp裡的func()計算內容? 事實上,它不會那麼做。一般會有這種錯覺,是因為IDE替你作了。一般會有個makefile ,就像個批次檔,會把每個原始檔編譯,各產生目的檔,再連結起來。如果你全部用手動 進行,就要一個一個下命令。 : 是在build solution的時候嗎?如果是的話,那是用什麼方法把他們連結起來的? 用連結器。 : 是在build的時候,遇到a1.func()的時候,去class.cpp(class.obj ? )裡找相對應的function, : 把function寫進執行檔裡並將a1.func()指到那個function存在的位址嗎? 連結器會看看每個目的檔中,參照了哪個函式。並且確保大家的坑都有蘿剝插。 : 4.只是好奇,如果我在class外,寫了三個function(有兩個沒有用到), 雖然 : 沒用到應該刪掉或註解掉,但是如果我沒註解掉, : 那我的執行檔裡會存三個還是一個function呢? 這樣的函數,一樣會存在。也許不同的compiler有不同的作法? : 5.所以template跟inline function,如果存成兩個file class.h class.cpp : build solution會有問題,是因為build的過程,main.obj裡的所用到的 : tmeplate function並沒有在compile的過程替換成所應該對應的type : 導致main.obj在class.obj裡找不到對應的function? 是的,那表示你的instance無法被推導(induction)。template較為特殊,因為它必需 以原始碼型態存在於你的編譯標的中。若它被編譯後,才進行連結,那你的instance 就無法被推導了。 在c++ templates: the complete guide中有提及這些問題,並且衍生出原始碼是否應 該公開的討論。 考慮下列程式: callee.cpp: #include <cstdio> #include "callee.hpp" template <typename T> void callee(T var){ printf("The size of argument is %d\n", sizeof(var)); } callee.hpp template <typename T> void callee(T var); caller.cpp #include <cstdio> #include "callee.hpp" //Notice this line!!! int main(int argc, char *argv[]) { callee(10); callee("str"); return; } 若是傳統的C或C++,則我標明的那行,不管是放callee.hpp,或是callee.cpp,都不會錯 但若是用了template,則一定要改成callee.cpp,否則會報錯,因為它在callee.obj中 找不到具callee(int)及callee(char *)兩原型的函數。所以一定要把callee.cpp給 caller.cpp引入,而不能只給obj檔,否則就無法推導。 : 那為什麼compiler會想把main.cpp裡的template function做替換 : 然後製做出main.obj : 而不是 : 在build solution的時候再做替換,直接把替換過的function寫入執行檔? : 有什麼壞處嗎?除了main.obj裡沒有相對應的function... we dicussed above. -- -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 218.166.202.127 ※ 編輯: ccbruce 來自: 218.166.202.127 (03/25 18:54) ※ 編輯: ccbruce 來自: 218.166.202.127 (03/25 19:03)

03/25 19:07, , 1F
謝謝你詳細的解說,感謝,總算比較有一點概念^^
03/25 19:07, 1F
文章代碼(AID): #149HI6I- (C_and_CPP)
文章代碼(AID): #149HI6I- (C_and_CPP)