了解编译和链接

在步入工作岗位之后,重新对编程是个什么过程进行了了解

简单的来说,我们平常所写的代码经过编译和链接之后生成可执行文件,下面就编译和链接两个过程分别讨论

编译阶段

编译阶段需要的素材就是你的源文件,把源文件经过一系列神奇的编译操作变成目标文件就是我们的目的,也就是linux系统下使用gcc -o得到的目标文件

预处理简单来说就是宏的展开和头文件的包含,把#include的东西全都复制进去,把文件变大,但是语言本质并没有改变,也就是说你的C还是原来的C

编程语言到汇编语言就是编译器做的工作了,一个好的编译器在这里会下很大的功夫。

可以这么理解,汇编语言和机器语言基本是等价的,区别只不过是汇编语言还是给人看的,机器语言已经不是给人看的了是给机器看的(当然你要是精通机器语言也是吼的),为什么这么说?每一条汇编语言都有机器语言去对应,每一个汇编命令都是遗传二进制码

编译的结果是生成目标文件,每一个编译单元生成对应的一个目标文件,这里还是可以参考linux系统下的gcc -o,使用这条命令的时候会把每个.c文件的文件名拿来直接生成对应的.o文件(就是helloworld.c->helloworld.o)

链接阶段

上图是各个文件相互转化的图。目标文件可以直接生成可执行文件,也可以做成动态库或者静态库,静态库可以链接另一个静态库变成一个更大的库。诸如此类的转化

提到链接就有很多熟悉的名词和概念要提

静态库

静态库在程序编译的时候会被链接到目标代码当中,所以在程序运行的时候就不再需要静态库啦,相当于可执行程序把静态库包含了。

动态库

与静态库相对的动态库,在程序编译的时候并不会被链接到目标代码当中,而是在程序运行的时候才被载入,因此在程序运行的时候还需要动态库的存在,这就是在运行一些软件的时候你会看到一个警告框,提醒你缺少摸个.dll文件的原因

静态链接

静态链接是指在链接的过程中直接将需要执行的代码(函数)拷贝到调用的地方,在程序运行的时候不在需要依赖链接的库,也不用带着库一起发布,程序就可以独立运行,但是程序的体积可能会大一些,因为会把一些代码塞进可执行程序里面

动态链接

与静态链接相对的,动态链接不会在链接的过程中把代码拷贝到调用的地方,动态链接会把调用的地方记录一些符号和参数(例如生成一个函数对应的符号),在程序运行到这个调用的地方的时候,可执行程序会把这些符号和参数传递给操作系统,操作系统会根据需要把对应的动态库加载到内存,然后可执行程序就可以去这段内存中寻找动态库中的代码,同时因为加载到共享的内存中可以供多个程序共同使用,这就是所谓的运行时链接。相比静态链接来说,由于不向可执行程序中拷贝代码,使得程序的体积在一定意义上减小了。因为动态链接将库加载到内存,省去了在各个程序中的拷贝,减少了磁盘的占用,可以让多个程序共享使用。但是缺点是加载需要一定的事件,可能会影响一定的性能

总结

一般来讲,静态链接和静态库对应使用,动态链接和动态库对应使用。据说有方法可以有别的使用方法,这里就不讨论了,有兴趣的可以搜索下

时间: 2024-10-17 08:33:52

了解编译和链接的相关文章

编译原理 (预处理>编译>汇编>链接)(转)

一般高级语言程序编译的过程:预处理.编译.汇编.链接.gcc在后台实际上也经历了这几个过程,我们可以通过-v参数查看它的编译细节,如果想看某个具体的编译过程,则可以分别使用-E,-S,-c和 -O,对应的后台工具则分别为cpp,cc1,as,ld.下面我们将逐步分析这几个过程以及相关的内容,诸如语法检查.代码调试.汇编语言等. 1.预处理 预处理是C语言程序从源代码变成可执行程序的第一步,主要是C语言编译器对各种预处理命令进行处理,包括头文件的包含.宏定义的扩展.条件编译的选择等.打印出预处理之

GCC编程四个过程:预处理-编译-汇编-链接

在Linux下进行C语言编程,必然要采用GNU GCC来编译C源代码生成可执行程序. 一.GCC快速入门Gcc指令的一般格式为:Gcc [选项] 要编译的文件 [选项] [目标文件]其中,目标文件可缺省,Gcc默认生成可执行的文件名为:编译文件.out我们来看一下经典入门程序"Hello World!"# vi hello.c #include <stdlib.h>#include <stdio.h>void main(void){printf("he

《程序员的自我修养》 第二章——编译和链接

摘自http://blog.chinaunix.net/uid-26548237-id-3839979.html <程序员的自我修养>第二章——编译和链接 2.1 被隐藏了的过程    C语句的经典,“Hello World”程序几乎是每个程序员闭着眼睛都能写出的,编译运行一气呵成,基本成了程序入门和开发环境测试的默认标准. #include <stdio.h> int main() { printf("Hello World\n"); return 0; 在L

C++编译与链接(1)-编译与链接过程

大家知道计算机使用的一系列的1和0 那个一个C++语言程序又是如何从一个个.h和.cpp文件变成包含1和0的可执行文件呢? 可以认为有以下的几个阶段 源程序->预处理->编译和优化->生成目标文件->链接->可执行文件 1.预处理 C++的预处理是指在C++程序源代码被编译之前,由预处理器对C++程序源代码进行的处理.这个过程并不对程序的源代码进行解析. 这里的预处理器(preprocessor)是指真正的编译开始之前由编译器调用的一个独立程序. 预处理器主要负责以下的几处

详解编译、链接

被隐藏了的过程    现如今在流行的集成开发环境下我们很少需要关注编译和链接的过程,而隐藏在程序运行期间的过程可不简单,即使使用命令行来编译一个源代码文件,简单的一句"gcc hello.c"命令就包含了非常复杂的过程. 1 #include<stdio.h> 2 3 int main() 4 { 5 printf("Hello word\n"); 6 return 0; 7 } 在Linux系统下使用gcc编译程序时只须简单的命令: $gcc hell

C++编译与链接(0)-.h与.cpp中的定义与声明

C++中有的东西需要放在可以在.h文件中定义,有的东西则必须放在.cpp文件中定义,有的东西在不同的cpp文件中的名字可以一样,而有的则不能一样 那么究竟哪些东西可在头文件中定义,声明,哪些东西又必须在.cpp中定义,声明呢? *以下所有的讨论都是在全局命名空间中(即不定义自己的namespace)下进行的 函数 1.在.h中只能声明函数,在.cpp中可以声明与定义函数 如果在.h中声明并定义一个函数,则该函数只能被#include一次,否则则会出现重定义错误 比如 1.h #pragma on

C语言预处理 编译 汇编 链接四个阶段

c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接. 编译过程 编译过程又可以分成两个阶段:编译和会汇编. 编译 编译是读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,源文件的编译过程包含两个主要阶段: 第一个阶段是预处理阶段,在正式的编译阶段之前进行.预处理阶段将根据已放置在文件中的预处理指令来修改源文件的内容.如#include指令 就是一个预处理指令,它把头文件的内容添加到.cpp文件中.这个在编译之前修改源文件的方式提供

读书笔记:程序员的自我修养-----第二章(编译和链接)

自己之前一直以为目标文件是经过汇编生成.s之后编译生成的,好菜. 源程序到可执行程序过程:预处理  编译 汇编 链接 预处理: 展开宏定义,处理条件预编译指令,插入头文件,删除注释,添加行号和文件名标示,保留#pragma编译器指令. 编译: 词法分析:词法扫描器按照词法规则产生记号,根据记号放入到相应表中.比如讲标示符放入符号表,将数字和字符串常量防盗文字表等. 语法分析:产生以表达式为节点的语法树 语义分析:语义分析器所能分析的只是静态语义(声明,类型的匹配,类型的转换),语义分析之后,每个

C语言学习入门 (一) 编译、链接、关键字、数据类型、printf函数

参考链接:http://blog.csdn.net/jjwwmlp456/article/details/41676225 编译文件:cc -c one.c two.c  生成.o目标文件 链接文件:cc one.o two.o     默认生成 a.out 执行文件 指定生成的可执行文件名   cc -o one one.o 连续编译.链接:cc one.c      cc -o one one.c    中间生成的.o文件会被删除,最后生成执行文件 cc one.c two.c   源文件超