<p id="34J7MRP1">看完这篇文章之后,终于明白了编译到底怎么回事。</p><p id="34J7MRP2">1</p><p id="34J7MRP3">对于同一个语句,有如下三种:高级语言、低级语言、机器语言的表示</p><p id="34J7MRP4">C语言:</p><p><blockquote id="34J7MRQG">a=b+1;<br/></blockquote></p><p id="34J7MRP6">汇编语言:</p><p><blockquote id="34J7MRQH">mov -0xc(%ebp),%eax<br/>add $0x1,%eax<br/>mov %eax,-0x8(%ebp)<br/></blockquote></p><p id="34J7MRP8">机器语言:</p><p><blockquote id="34J7MRQI">8b 45 f4<br/>83 c0 01<br/>89 45 f8<br/></blockquote></p><p id="34J7MRPA">我们都知道,机器是只能做数字计算的,能够让机器去运算的、数字的语言就是机器语言,除此之外的所有计算机语言都是非机器语言。</p><p id="34J7MRPB">这样的相对于机器语言的高级语言都需要一个转换,从高级、机器不可理解,转换为机器可理解的机器语言。</p><p id="34J7MRPC">这样的一个转换过程就叫做<strong>编译(Compile)</strong>,由<strong>编译器(Compiler)</strong>来完成。</p><p id="34J7MRPD">由C转换为汇编语言这一过程是由<strong>汇编器</strong><strong>(Assembler)</strong>来执行的。</p><p id="34J7MRPE">C和汇编语言转换为机器语言都是由编译器来完成的。</p><p id="34J7MRPG">2</p><p id="34J7MRPH">这里面,C是可跨平台的,也可以说是与平台无关的。这里的平台有两种说法,一种是指<strong>计算机的体系(Architecture)</strong>,另一种是指<strong>操作系统(Operate System)</strong>,也可以是指两种的结合。</p><p id="34J7MRPI">不同的平台,他们所需要的执行机器语言的指令集是不同的。C的跨平台性是指,只需要编写一份不需要修改的C程序代码,就可以在不同体系、不同操作系统的计算机上运行。</p><p id="34J7MRPJ">这都要靠编译器的功劳,编译器将C程序翻译为了适合当前计算机体系的机器语言。</p><p id="34J7MRPK">下面说一下将C语言编译为机器语言的整个过程:</p><p id="34J7MRPL">首先,我们写出一份C程序代码,命名该代码为hello.c,这个代码文件,我们称之为源代码(Srouce Code)。</p><p id="34J7MRPM">然后我们运行编译器,对该源代码文件进行编译,在整个编译的过程中,编译器并不会执行该源代码,只是生成一份新的机器语言代码文件,如<strong>hello.out</strong>。</p><p id="34J7MRPN">这份新生成的代码文件称为目标代码(Object Code)或可执行代码(Executable)。</p><p id="34J7MRPP">3</p><p id="34J7MRPQ">对于编译过程,里面还涉及到具体的一些可以说的细节步骤。<strong>在Linux下,使用gcc编译器:</strong></p><p id="34J7MRPR"><strong>❀ 预编译hello.c文件:</strong></p><p><blockquote id="34J7MRQJ">gcc -E -o hello.i hello.c<br/></blockquote></p><p id="34J7MRPT">执行成功后就会生成一个新的<strong>hello.i</strong>的文件,可以用编辑器(Vim)查看它的内容,这个文件就是经过预编译后的内容。</p><p id="34J7MRPU">预编译又称为预处理,是做些代码文本的替换工作。预编译可以处理#开头的指令,比如拷贝<strong>#include</strong>包含的文件代码,#define的宏定义的替换,条件编译等。</p><p id="34J7MRPV"><strong>❀ 纯粹的进行编译:</strong></p><p><blockquote id="34J7MRQK">gcc -S -o hello.s hello.i<br/></blockquote></p><p id="34J7MRQ1">把<strong>.i</strong>文件写为<strong>hello.c</strong>也行,就是跳过手动预编译,直接完成预编译和编译两个过程。</p><p id="34J7MRQ2">这时会得到一个<strong>hello.s</strong>文件,打开看一下,里面是编译好的使用于当前体系结构的汇编代码。</p><p id="34J7MRQ3"><strong>❀ 把汇编代码处理为</strong><strong>目标文件</strong><strong>:</strong></p><p><blockquote id="34J7MRQL">gcc -c -o hello.o hello.s<br/></blockquote></p><p id="34J7MRQ5">把<strong>.s</strong>文件换成<strong>.c</strong>也行,就是自动完成预编译、编译和汇编三个过程。</p><p id="34J7MRQ6">现在得到一个<strong>hello.o</strong>文件,这是一个二进制文件,但不是最后的可执行二进制文件,因为它还缺少最后一步连接处理。</p><p id="34J7MRQ7">最后对目标文件<strong>.o</strong>文件进行连接,我们这里就一个<strong>.o</strong>文件所以简单,经常是需要有多个<strong>.o</strong>文件需要连接。</p><p id="34J7MRQ8"><strong>❀ 连接执行:</strong></p><p><blockquote id="34J7MRQM">gcc -o hello hello.o<br/></blockquote></p><p id="34J7MRQA">如果把最后的<strong>.o</strong>文件写成<strong>.c</strong>,那就和最开始我们用<strong>hello.c</strong>编译时示范的那样了。实际上那样是完成了预编译、编译、汇编和连接一连串的过程。</p><p id="34J7MRQB"><strong>-o</strong>选项给输出的文件重新命名而不使用<strong>gcc</strong>默认的文件名。</p><p id="34J7MRQC">想了解更多<strong>gcc</strong>的姿势可以到GNU上去看看。</p><p class="f_center"><img src="https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2024%2F1028%2F79a6b938j00sm2ahp0049d000h400dwp.jpg&thumbnail=660x&quality=80&type=jpg"/><br/><br/></p>
讯享网

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/191910.html