仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2911|回复: 7
打印 上一主题 下一主题

[C++基础] 来一发编译器的事情历程和道理

[复制链接]
兰色精灵 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-16 11:05:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
安装和登录命令:login、shutdown、halt、reboot、mount、umount、chsh
  码要运转,必需先转成二进制的呆板码。这是编译器的义务。
  好比,上面这段源码(假定文件名叫做test.c)。
  1. #include<stdio.h>intmain(void){fputs("Hello,world!
  2. ",stdout);return0;}
复制代码
  要先用编译器处置一下,才干运转。
  1. $gcctest.c$./a.outHello,world!
复制代码
  关于庞大的项目,编译历程还必需分红三步。
  1. $./configure$make$makeinstall
复制代码
  这些命令究竟在干甚么?年夜多半的书本和材料,都语焉,只说如许就能够编译了,没有进一步的注释。
  本文将先容编译器的事情历程,也就是下面这三个命令各自的义务。我次要参考了AlexSmith的文章《BuildingCProjects》。必要声明的是,本文次要针对gcc编译器,也就是针对C和C++,纷歧定合用于其他言语的编译。



  第一步设置(configure)
  编译器在入手下手事情之前,必要晓得以后的体系情况,好比尺度库在那里、软件的安装地位在那里、必要安装哪些组件等等。这是由于分歧盘算机的体系情况纷歧样,经由过程指定编译参数,编译器就能够天真顺应情况,编译出各类情况都能运转的呆板码。这个断定编译参数的步骤,就叫做”设置”(configure)。
  这些设置信息保留在一个设置文件当中,商定俗成是一个叫做configure的剧本文件。一般它是由autoconf工具天生的。编译器经由过程运转这个剧本,获知编译参数。
  configure剧本已只管思索到分歧体系的差别,而且对各类编译参数给出了默许值。假如用户的体系情况对照出格,大概有一些特定的需求,就必要手意向configure剧本供应编译参数。
  1. $./configure--prefix=/www--with-mysql
复制代码
  下面代码是php源码的一种编译设置,用户指定安装后的文件保留在www目次,而且编译时到场mysql模块的撑持。
  第二步断定尺度库和头文件的地位
  源码一定会用到尺度库函数(standardlibrary)和头文件(header)。它们能够寄存在体系的恣意目次中,编译器实践上没举措主动检测它们的地位,只要经由过程设置文件才干晓得。
  编译的第二步,就是从设置文件中晓得尺度库和头文件的地位。一样平常来讲,设置文件会给出一个清单,列出几个详细的目次。比及编译时,编译器就按按次到这几个目次中,寻觅方针。
  第三步断定依附干系
  关于年夜型项目来讲,源码文件之间常常存在依附干系,编译器必要断定编译的前后按次。假定A文件依附于B文件,编译器应当包管做到上面两点。
(1)只要在B文件编译完成后,才入手下手编译A文件。
(2)当B文件产生变更时,A文件会被从头编译。
  编译按次保留在一个叫做makefile的文件中,内里列出哪一个文件先编译,哪一个文件后编译。而makefile文件由configure剧本运转天生,这就是为何编译时configure必需起首运转的缘故原由。
  在断定依附干系的同时,编译器也断定了,编译时会用到哪些头文件。
  第四步头文件的预编译(precompilation)
  分歧的源码文件,大概援用统一个头文件(好比stdio.h)。编译的时分,头文件也必需一同编译。为了节俭工夫,编译器会在编译源码之前,先编译头文件。这包管了头文件只需编译一次,不用每次用到的时分,都从头编译了。
  不外,并非头文件的一切内容,城市被预编译。用来声明宏的#define命令,就不会被预编译。
  第五步预处置(Preprocessing)
  预编译完成后,编译器就入手下手交换失落源码中bash的头文件和宏。以本文开首的那段源码为例,它包括头文件stdio.h,交换后的模样以下。
  1. externintfputs(constchar*,FILE*);externFILE*stdout;intmain(void){fputs("Hello,world!
  2. ",stdout);return0;}
复制代码
  为了便于浏览,下面代码只截取了头文件中与源码相干的那部分,即fputs和FILE的声明,省略了stdio.h的其他部分(由于它们十分长)。别的,下面代码的头文件没有经由预编译,而实践上,拔出源码的是预编译后的了局。编译器在这一步还会移除正文。
  这一步称为”预处置”(Preprocessing),由于完成以后,就要入手下手真实的处置了。
  第六步编译(Compilation)
  预处置以后,编译器就入手下手天生呆板码。关于某些编译器来讲,还存在一其中间步骤,会先把源码转为汇编码(assembly),然后再把汇编码转为呆板码。
  上面是本文开首的那段源码转成的汇编码。
  1. .file"test.c".section.rodata.LC0:.string"Hello,world!
  2. ".text.globlmain.typemain,@functionmain:.LFB0:.cfi_startprocpushq%rbp.cfi_def_cfa_offset16.cfi_offset6,-16movq%rsp,%rbp.cfi_def_cfa_register6movqstdout(%rip),%raxmovq%rax,%rcxmovl$14,%edxmovl$1,%esimovl$.LC0,%edicallfwritemovl$0,%eaxpopq%rbp.cfi_def_cfa7,8ret.cfi_endproc.LFE0:.sizemain,.-main.ident"GCC:(Debian4.9.1-19)4.9.1".section.note.GNU-stack,"",@progbits
复制代码
  这类转码后的文件称为工具文件(objectfile)。
  第七步毗连(Linking)
  工具文件还不克不及运转,必需进一步转成可实行文件。假如你细心看上一步的转码了局,会发明个中援用了stdout函数和fwrite函数。也就是说,程序要一般运转,除下面的代码之外,还必需有stdout和fwrite这两个函数的代码,它们是由C言语的尺度库供应的。
  编译器的下一步事情,就是把内部函数的代码(一般是后缀名为.lib和.a的文件),增加到可实行文件中。这就叫做毗连(linking)。这类经由过程拷贝,将内部函数库增加到可实行文件的体例,叫做静态毗连(staticlinking),后文会提到另有静态毗连(dynamiclinking)。
  make命令的感化,就是从第四步头文件预编译入手下手,一向到做完这一步。
  第八步安装(Installation)
  上一步的毗连是在内存中举行的,即编译器在内存中天生了可实行文件。下一步,必需将可实行文件保留到用户事前指定的安装目次。
  外表上,这一步很复杂,就是将可实行文件(连带相干的数据文件)拷贝已往就好了。可是实践上,这一步还必需完成创立目次、保留文件、设置权限等步骤。这全部的保留历程就称为”安装”(Installation)。
  第九步操纵体系毗连
  可实行文件安装后,必需以某种体例关照操纵体系,让其晓得可使用这个程序了。好比,我们安装了一个文本浏览程序,常常但愿双击txt文件,该程序就会主动运转。
  这就请求在操纵体系中,挂号这个程序的元数据:文件名、文件形貌、联系关系后缀名等等。Linux体系中,这些信息一般保留在/usr/share/applications目次下的.desktop文件中。别的,在Windows操纵体系中,还必要在Start启动菜单中,创建一个快速体例。
  这些事变就叫做”操纵体系毗连”。makeinstall命令,就用来完成”安装”和”操纵体系毗连”这两步。
  第十步天生安装包
  写到这里,源码编译的全部历程就基础完成了。可是只要很少一部分用户,乐意耐着性质,从头至尾做一遍这个历程。现实上,假如你只要源码能够交给用户,他们会认定你是一个不友爱的家伙。年夜部分用户要的是一个二进制的可实行程序,立即就可以运转。这就请求开辟者,将上一步天生的可实行文件,做成能够分发的安装包。
  以是,编译器还必需有天生安装包的功效。一般是将可实行文件(连带相干的数据文件),以某种目次布局,保留成紧缩文件包,交给用户。
  第十一步静态毗连(Dynamiclinking)
  一般情形下,到这一步,程序已能够运转了。至于运转时代(runtime)产生的事变,与编译器一概有关。可是,开辟者能够在编译阶段选择可实行文件毗连内部函数库的体例,究竟是静态毗连(编译时毗连),仍是静态毗连(运转时毗连)。以是,最初还要提一下,甚么叫做静态毗连。
  后面已说过,静态毗连就是把内部函数库,拷贝到可实行文件中。如许做的优点是,合用局限对照广,不必忧虑用户呆板短少某个库文件;弱点是安装包会对照年夜,并且多个使用程序之间,没法共享库文件。静态毗连的做法恰好相反,内部函数库不进进安装包,只在运转时静态援用。优点是安装包会对照小,多个使用程序能够共享库文件;弱点是用户必需事前安装好库文件,并且版本和安装地位都必需切合请求,不然就不克不及一般运转。
  实际中,年夜部分软件接纳静态毗连,共享库文件。这类静态共享的库文件,Linux平台是后缀名为.so的文件,Windows平台是.dll文件,Mac平台是.dylib文件。
文件处理命令:file、mkdir、grep、dd、find、mv、ls、diff、cat、ln
再见西城 该用户已被删除
沙发
发表于 2015-1-18 07:47:01 | 只看该作者
一开始你问得问题他一定可以解决,所以这个时候你如坐春风,一日千里;慢慢得你一定可以提出强人解决不了得问题(不管那方面技术),这个时候可以说你已经入门了,把强人解决不了任务解决掉,解决掉你自己一定很有成就感;
飘飘悠悠 该用户已被删除
板凳
发表于 2015-1-24 19:20:17 | 只看该作者
慢慢得,你会发现你得问题强人基本解决不了,不是你超过他,而是你们关注领域不同,这个时候,你自己也成为强人了,嘿嘿!!
柔情似水 该用户已被删除
地板
发表于 2015-2-7 22:23:10 | 只看该作者
不耻上问。初学者有时候碍于面子,抑或是怕人家笑话而不敢问问题。没有必要,你问得人以前也是一样过来得。前提找一个技术上大家认为强得,而且容易交流得。
因胸联盟 该用户已被删除
5#
发表于 2015-2-23 14:50:26 | 只看该作者
用的vector,而很少使用了数组。当然在我现在的能力范围内,还很难驾驭vector,毕竟数组当年也是我的最爱,相比于更加难缠的指针控制来说。
金色的骷髅 该用户已被删除
6#
发表于 2015-3-7 09:41:14 | 只看该作者
在与别人合作中,可以学习到她们的优点,可以得到自己想不到的学习方法,与此同时,还可以增进我们的友谊。
透明 该用户已被删除
7#
发表于 2015-3-14 22:54:58 | 只看该作者
在实际操作过程中犯的一些错误还会有意外的收获,感觉实训很有意思。在具体操作中对这学期所学的C++语言的理论知识得到巩固,达到实训的基本目的,也发现自己的不足之出,在以后的上机中应更加注意。
兰色精灵 该用户已被删除
8#
 楼主| 发表于 2015-3-21 17:53:10 | 只看该作者
照着书上(好书,大家认可得)敲,编译,并思考,你会发现很多问题,解决问题的同时你正在提高。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-22 14:07

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表