1.translation unit(翻译单元或编译单元?)
参考链接:
https://stackoverflow.com/questions/1106149/what-is-a-translation-unit-in-c(需科学上网)
http://www.ruanyifeng.com/blog/2014/11/compiler.html
http://blog.chinaunix.net/uid-27018250-id-4305502.html
第一个链接中的高票答案:
According to standard C++ (wayback machine link) : 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.
A single translation unit can be compiled into an object file, library, or executable program.
The notion of a translation unit is most often mentioned in the contexts of the One Definition Rule, and templates.
我的理解:
编译单元当然是针对编译器来说的。编译器将源文件编译成可执行文件(硬件可直接执行的二进制机器码)经过下面的步骤
1.precompilation(预编译或预处理)(有些文章分得更细,将预编译与预处理分成两个部分)
处理#开头的指令,比如拷贝#include包含的文件代码,#define宏定义的替换,条件编译等
对于gcc来说,经过此步骤后的源文件变为以.i结尾的文件
2.compilation(编译)
将预处理后的文件编译成汇编文件。对于gcc来说,是以.s结尾的文件
3.assemble(汇编)
将汇编文件转换成机器码文件。对于gcc来说,是以.o结尾的文件,也叫目标文件
4.linking(链接)
将多个目标文件与程序所需的库文件(以.so结尾等)链接成可执行文件
答案中说一个编译单元包括一个源文件和源文件引用的头文件。这样看上去貌似有些矛盾,其实不然。源文件中虽然引用了头文件,但并没有头文件的实体内容。所以结合来看,编译单元的语义作用域是在编译期间的第1到第3个过程。一个编译单元类似于一个.i文件或者.s文件。答案中又说一个编译单元能被编译成一个目标文件,所以在编译步骤3之后,就不存在编译单元的说法了
2.internal linakge 和 external linkage(内部链接与外部链接)
首先,内部链接与外部链接是针对变量和函数而言的。并且这两个概念与上文的编译单元息息相关。
我们知道,可以用extern关键字引用其他源文件中的全局变量或自由函数(不严谨的讲就是不是成员函数和友元函数的函数,平时写在mian函数外的函数就属于自由函数)。但对于一个编译单元(源文件)来说,编译单元中如果有变量或函数是从其他编译单元(源文件)引用过来的,那么就必须通过链接(linking)将其组合,才能使引用了其他编译单元中的变量或函数的编译单元正确运行。这样被其他编译单元(源文件)引用的变量或函数,就是外部链接的。反之就是内部链接的。
对于某个源(头)文件的全局变量或自由函数来说,只要我在另一个源文件include了这个文件,就可以通过extern关键字引用它,这时这个全局变量或自由函数就可以说是被外部链接了。外部就是其他编译单元啦。如果不想被外部引用,可以将全局变量或自由函数加上static关键字。
给自由函数加上static关键字与给非自由函数加上static关键字不同。对于类中的被static修饰的函数来说,此函数属于类而非对象,符合语义化的调用方式是使用类名调用。既然此函数属于类而非对象,它当然也就不能修改非静态的数据成员和调用成员函数了。而对于自由函数来说,static关键字对其的限制与对全局变量的限制相同,即此函数或变量只能在本文件中被使用,其他源文件不能通过extern来引用。