您的位置:首页 > 编程语言 > C语言/C++

C++编程思想——编译与连接

2014-11-06 09:14 127 查看

编译与链接

昨天去面试的时候真心被好好的鄙视了一下,我感觉对不起编译原理的老师,发现我有太多的不懂,好好的做个总结。

编译器

将源代码转化为汇编语言或机器指令。其实质是分为两步:

1)对与处理过的代码进行词法分析、语法分析,生产语法树。

2)将语法树中的每个节点都转化为汇编语言或机器代码。也就是生产目标模块,以.o或者.obj为拓展名的文件。

拓展点:1)预处理。在C或者是C++中,都要对源代码进行预处理,利用程序员定义好的模式替换代码中的模式,主要是用来节省输入,增加代码的可读性。

2)在第一步与第二步中间会使用全局优化器生产更短、更快的代码。

3)这里注意声明与定义的区别,声明是告诉编译器函数或者变量的名字,而定义的话,编译器将会其分配空间。那么头文件就是一个含有某个库的外部声明函数和变量的文件。定义有的时候我们int a对于变量使用extern说明它只是一个声明。

链接器

将一组目标模块链接成一个可执行为文件,也就是操作系统可以装载和运行它。当某个目标模块中的函数要引用另一个目标模块中的函数或变量时,由链接器来处理这种引用。注意由于早期的链接器对目标文件和库文件只查找一次,因此目标文件和库文件的顺序特别重要。那么链接器如何查找库的呢?

当C或C++要对函数和变量进行外部引用时,链接器如果还未遇到过这个函数或变量的定义,则将它的标识符加到“未解决的引用”列表中,那么它将会去查找库,对库的查找使用的是索引方式,它只浏览索引。然后将整个目标模块链接到可执行程序中,只是需要的模块,并不是整个库文件。对于已经遇到过的函数或者变量,就是已经解决的引用。

拓展:

1)链接器会添加一个目标模块来完成程序的启动任务。在创建应用程序项目时,集成开发环境会设置各种连接器开关,使得连接器将子系统的正确类型嵌入到最终生成的可执行文件中。操作系统会在链接时使用-entry:命令行选项来设置一个C/C++运行时的启动函数,该函数将初始化C/C++运行库,如此才能够使用malloc等函数。调用crtexe.c文件中的4个启动函数,其用途为:a.获取指向进程的完整命令行的一个指针;b.获取指向新进程的环境变量的一个指针;c.初始化运行库的全局变量;d.初始化C运行库内存分配函数和其它底层I/O例程使用的堆;e.调用所有全局和静态C++类对象的构造函数。

2)对于static以及extern分别使用内部链接以及外部链接。内部链接只对正被编译的文件创建存储空间,因此别的文件可以使用相同的标识符或者全局变量。每个标识符有单独的存储空间,它们之间并不会发生冲突。外部链接为所有编译过的文件创建一片单独的存储空间。全局变量和函数名有外部链接。当然你可以是用static强制它们具有内部链接。在调用函数时,局部变量知识存在堆栈中,链接器不知道自动变量,也就没有链接。

3)说说static作用:a.在函数体中其值不变;b.在模块内,被声明为静态的变量只能被模块内的函数访问。C.在模块内,声明为静态的函数只被该模块的其它函数调用

4)Static可以强制全局变量有内部链接,它就是一个static全局变量,只初始化一次,防止其在其它文件单元中被引用。它与普通函数的区别是,下一次会更根据上一次的结果,由上面的分析我们也不难得出。Static函数在内存中只有一份,而普通的函数在每个被调用中都维持一份复制品。

.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: