c++ 编译链接 相关【 原创 + 转载】

来源:互联网 发布:linux 内核源码修改 编辑:程序博客网 时间:2024/06/04 01:24

先 写下 几个 名词 : 预处理, 编译(obj), 链接(exe),  编译单元, 内部链接, 外部链接

( 在 看 之前 要对  c++ 中 的  声明 定义 初始化  左值 右值 掌握  ,很容易混。 网上 很多 名词 用的不恰当或 错误, 本文很可能有 0.0 欢迎指正

预处理主要负责 : 1.宏的替换

      2.删除注释(编译器参数 可以设置)

   3.处理预处理指令 (#include, #ifdef), 把头文件中的 声明 加到cpp文件中



编译单元 : 指的是 单个.cpp文件 且 包括 该cpp文件中 包含的头文件(递归包含)

.h文件是不会被编译器单独编译的 [c++ 中的 .hpp文件 简单一提  像是头文件 和 实现文件的结合]

编译器会为每个编译单元进行编译, 生成相应的obj文件

然后链接器将所有obj文件 进行链接, 生成可执行文件。


内部链接,

外部链接  : 这两个 名词 指的都是 代码中的 变量(不只是 “变量”)的属性。

如果 一个名称 对于一个 编译单元来说 是 局部的,且 在链接的时候不可能与

其他的编译单元中的 同名 变量 冲突, 则 这个变量就是具有 内部链接的。


外部链接 相对 内部链接, 就是变量 能被引入 目标文件(.obj)中,对其他编译单元

可见。 对其的 要求是 名字唯一。


然后说下 各种标识符 会给 变量带来什么 影响 :

举个例子 :static int x, 

enum Bollean {eFalse, eTrue};

class T {}; inline int operator==(const Point& _left, 

const Point& _right);

以上都是 具有 内部链接属性的 ;再来看下 外部链接

外部链接:    非内联的类成员函数 Point& Point::operator+=(Point const& right) {}

非内联, 非静态的自由函数 Point operator+=(Point const& left, Point const& right){}

非静态的 全局定义


上面大体说了下 有个 感性认识  然后 在 继续 细说:

extern:  他是 声明符 意在 表明 这只是个声明 告诉你 有这么个东西 到别处(其他编译单元等)找。

extern把其修饰的变量 凡在 为解决符号表(这个表 也忘说了.. 一共 2 个 还是 3 个,还有个 虚函数表vtb)里。

static : 说过了,但凡是 被 修饰的 都是 内部链接 不 导出 。

const : 默认 内部链接,  可通过 加 extern 和 static 来改变 

extern const int a = 35;

为什么头文件里一般只可以有声明不能有定义:   

头文件可以被多个编译单元包含,如果头文件里有定义,那么每个包含这个头文件的编译单元就都 

对同一个符号进行定义,如果该符号为外部链接,则会导致duplicated external simbols。因 

此如果头文件里要定义,必须保证定义的符号只能具有内部链接



    为什么常量默认为内部链接,而变量不是:
        这就是为了能够在头文件里如const int n = 0这样的定义常量。由于常量是只读的,因此即

使每个编译单元都拥有一份定义也没有关系。如果一个定义于头文件里的变量拥有内部链接,

那么如果出现多个编译单元都定义该变量,则其中一个编译单元对该变量进行修改,影响

其他单元的同一变量,会产生意想不到的后果。网上看到的 . 没看懂这句 解释 

个人理解 头文件中的 都必须是内部链接(我意思是 变量都应该是)  求 解答

To be continue ...




















0 0