A translation unit is the basic unit of compilation in C++. It consists of the contents of a single source file, plus the contents of any header files directly or indirectly included by it, minus those lines that were ignored using conditional preprocessing statements.
C++ 編譯過程中的基本單位,組成為原始碼 + 裡面有 include 進來的所有 header(不論是直接 include 還是間接 include 都有)並移掉由 conditional preprocessing statement 中不會走到的程式碼。簡單來說就是 preprocessor 處理後的內容。
Name Mangling (Name Decoration)
一種用來解決由於程式實體中名字必須唯一而導致的問題的技術,它提供了一種方式來加入額外的資訊在 function, structure, class name 中,這使得編譯器可以傳遞更多語意資訊給連結器。
使用時機在於當程式語言允許不同的程式實體但是卻用相同的識別字時,像是:
different namespace
different signature (e.g., function overloading)
main 是 implementation-defined 的函式,也就是不同編譯器有不同的結果(可能 mangle 也可能沒有)。
#include <iostream>
#include "sum.h" // sumI, sumF
void printSum(int a, int b) {
std::cout << a << " + " << b << " = " sumI(a, b) << std::endl;
}
void printSum(float a, float b) {
std::cout << a << " + " << b << " = " sumF(a, b) << std::endl;
}
extern "C" void printSumInt(int a, int b) {
printSum(a, b);
}
extern "C" void printSumFloat(float a, float b) {
printSum(a, b);
}
上面程式中,printSum 是一個 overloading function,也就是沒辦法直接被 C 使用,為了給 C 使用,可以用 wrapper function 像是上面的 printSumInt & printSumFloat,並且將它們用 extern "C" 去標註,好讓編譯器不會對他們做 mangling。接著用 nm 來看看 symbols:
$ g++ -c print.cpp
$ nm print.o
0000000000000132 T printSumFloat
0000000000000113 T printSumInt
U sumF
U sumI
0000000000000074 T _Z8printSumff
0000000000000000 T _Z8printSumii
U _ZSt4cout
T 代表位於 .text 區段。
可以看到用 extern "C" 定義的 wrapper function 並沒有被編譯器給 mangled。
接著來看看如何設計一個可以給 C & C++ include 的標頭檔,目標是讓 printSumInt & printSumFloat 可以被 C & C++ 呼叫,而 printSum 可以被 C++ 呼叫:
#ifdef __cplusplus
void printSum(int a, int b);
void printSum(float a, float b);
extern "C" {
#endif
void printSumInt(int a, int b);
void printSumFloat(float a, float b);
#ifdef __cplusplus
} // end extern "C"
#endif
__cplusplus:通常 C++ 編譯器中會自己定義這個 macro,因此不需要特地加 flag。
由於 printSumInt & printSumFloat 是 C++ code,若要用 C code 來呼叫並編譯成可執行檔必須使用 C++ 的 linker,像是 g++ -o c-app sum.o print.o c-main.o。
原文 "Surprisingly, variable names aren’t either needed in the definition of a function. They are only needed if you actually use the parameter in the function. But if you never use it you can leave the parameter with the type but without the name. Why would a function declare a parameter that it’d never use? Sometimes functions (or methods) are just part of an interface, like a callback interface, which defines certain parameters that are passed to the observer. The observer must create a callback with all the parameters that the interface specifies, since they’ll be all sent by the caller. But the observer may not be interested in all of them, so instead of receiving a compiler warning about an “unused parameter,” the function definition can just leave it without name."
How C++ Works: Understanding Compilation
Translation Unit (Compilation Unit)
Name Mangling (Name Decoration)
main
是 implementation-defined 的函式,也就是不同編譯器有不同的結果(可能 mangle 也可能沒有)。extern "C"
Sample print.cpp:
上面程式中,
printSum
是一個 overloading function,也就是沒辦法直接被 C 使用,為了給 C 使用,可以用 wrapper function 像是上面的printSumInt
&printSumFloat
,並且將它們用extern "C"
去標註,好讓編譯器不會對他們做 mangling。接著用nm
來看看 symbols:.text
區段。extern "C"
定義的 wrapper function 並沒有被編譯器給 mangled。sumF
,sumI
, &std::cout
這些在目前的 source file print.cpp 中並未定義,要在之後 linking 中跟別的 object file 或是 libraries 連結在一起才能夠使用。接著來看看如何設計一個可以給 C & C++ include 的標頭檔,目標是讓
printSumInt
&printSumFloat
可以被 C & C++ 呼叫,而printSum
可以被 C++ 呼叫:__cplusplus
:通常 C++ 編譯器中會自己定義這個 macro,因此不需要特地加 flag。printSumInt
&printSumFloat
是 C++ code,若要用 C code 來呼叫並編譯成可執行檔必須使用 C++ 的 linker,像是g++ -o c-app sum.o print.o c-main.o
。Include Guards
Forward Declaration
#include
而被開啟的檔案數,也就減少了需要的系統呼叫次數。a.h
跟b.cpp
,假設 b 只用到 a 中的某個類別或是某個函式,但是 a 中還有其他很多東西,若某天a.h
做了很大的更動,但是 b 使用到的部分並沒有更動,那麼這時候如果是使用#include
來使用a.h
內的東西,b.cpp
就會需要重新編譯,但是實際上b.cpp
使用到的部分根本跟之前一樣;若是使用 forward declaration 只有將需要用到的部分直接在b.cpp
中宣告,那麼就可以避免這個重複編譯的問題。MISC Stuff
nm
可以列出檔案中的 symbols-C
可以 demangle。using namespace std
不要放在標頭檔中,因為一旦被插入到原始碼中,後面的標頭檔也會同時擁有該 scope 底下的所有 symbols。這會造成一些名稱的混亂,畢竟對其他標頭檔來說預設可能是沒有這個 directive 的。