c语言系统概论

高级语言相较于低级语言:

汇编语言相较于ISA指令(机器码)而言可读性更好。但是这还是不够,因为相较于现实语言的自然表达而言还是太过于抽象了。

高级语言的作用就体现出来了。

对数值的符号命名(变量的定义)高级语言不用像汇编一样需要手工分配相应的内存地址,并注意不同类型的数据处理,而高级语言只需简单的分配一个名字及类型(变量名和变量的数据类型)即可,剩余的工作都由编译器自动完成(分配合适的地址,相关数据的搬移)。

高级语言表达能力能强,也更友好,更符合现实世界语言的自然表达形式。汇编需要编写大段大段的代码,而高级语言可能只需几行甚至1行即可。如三角形面积计算:高级语言可能只需这样即可area = 0.5 * base * height;(可读性更强)

高级语言对底层ISA或硬件做了抽象,通常底层指令不能直接支持某些操作,而高级语言直接提供了更加完整的操作集合(其实就是让自己需要写大段汇编代码以实现底层指令没有直接提供的操作的这个过程交给了高级语言去完成)。这样程序员可以集中在真正的编程任务上(其实就是更易编写,同时可读性也变得更强)

可靠性保证,在高级语言中,有严格的规则,程序在翻译或执行阶段将进行规则检查,如果出现规则冲突则会打印错误信息,更利于发现代码的问题(BUG),这样也提高了编码的效率。

 

本质上就是通过提高可读性,更简洁的编写方式,更完整功能集合,同时通过编译器保证代码的可靠性,将大大提高编写代码的效率。

 

高级语言是对指令相隔很远的上层抽象,但是最终还是需要编译为机器码以能被机器识别并执行。汇编语言通过汇编器即可完成,但是高级语言要经过的过程比汇编语言复杂漫长得多。

两种翻译方法:

解释执行:负责翻译的程序被称为“解释器”,高级语言被看做是一组“命令”集合,解释器逐个读入每天命令,然后按照语言规范的语义完成命令,高级语言是在解释器上执行而不是直接被硬件执行。解释器就像是一个虚拟机。每次读入高级语言程序的一行或一条命令,甚至是一个子程序,然后在实际硬件上运行一段相应的被解释器转化为机器码的代码。

编译执行:负责翻译的程序叫做“编译器”(其实包括了很多东西,像C语言就需要“预处理器”“编译器”“链接器”等等,只不过统称编译器),它将高级语言读入,然后编译为机器码(可执行映像),这个可执行映像可以直接在机器上执行。编译器本身不执行程序,仅负责翻译任务,即将高级语言转化为机器码。

解释执行的程序在开发和调试上比较方便,因为解释器每次执行一段即输出执行结果,这样可以程序员可以直接查看到中间结果并修改代码,同时解释执行的代码具有更好的可移植性(个人理解就是因为代码实际上是在解释器上执行的,和硬件无关,所以只要解释器本身支持在不同的操作系统上运行,执行的代码甚至可以完全不用做修改。如Java提出的once write,run anywhere本质就是java通过javac生成的是给JVM执行的文件,要让代码可以在不同的系统上运行,只需JVM本身能生成对应的机器码即可,和java代码完全无关了)

解释执行好处很多,但是也需要相应的代价,如执行时间相较编译执行的更长,因为存在中介“解释器”,而编译方式就没有这种问题了,并且编译方式在编译阶段能够对代码做更大的优化,这样产生的代码效率将会更高。

 

C编译器

先上图

预处理器:在正式编译之前,先对C程序做预处理,其实就是把所有C源文件中寻找并执行预处理指令,这些指令通常以“#”号开头,如#define a b(将文件中出现a的地方都用b来替换,这样的好处是如果b有变动,只需修改宏定义即可,而不用修改所有用到b的地方) #include a 就是把a文件的内容拷贝至源文件的当前位置。

编译器:经过预处理后,编译器继续翻译为“目标模块”,两个阶段:分析和合成。(实质过程就是把c程序翻译为汇编语言,再把汇编语言汇编为机器码)

通过语法分析和词法分析(代码的书写语法错误就是在这个过程发现)后生成等价的汇编代码。而在合成阶段则会进行代码的优化,并将优化后的代码通过汇编器转为二进制机器码。(优化是个大话题,知之甚少,暂且不提),符号表?

链接器:将各个目标模块组装成一个可执行映像(和汇编的链接过程很像,就是找出程序调用了库函数的地方,然后将库函数的代码做拷贝,然后链接入可执行映像)

链接又分静态链接和动态链接:

静态链接是指在编译阶段直接把静态库加入到可执行文件中去,这样可执行文件会比较大。

动态链接则是指链接阶段仅仅只加入一些描述信息,而程序执行时再从系统中把相应动态库加载到内存中去。

静态链接极大地浪费内存空间。因为在静态链接的情况下,假设有两个程序共享一个模块,那么在静态链接后输出的两个可执行文件中各有一个共享模块的副本。如果同时运行这两个可执行文件,那么这个共享模块将在磁盘和内存中都有两个副本,对磁盘和内存造成极大地浪费;第二,程序的更新。一旦程序中的一个模块被修改,那么整个程序都要重新链接、发布给用户。如果这个程序相当的大,那么后果就会更加严重!

 对于一个共享对象(linux下共享的模块),要实现被其他程序之间的共享,就要使其代码和数据分开,每个程序都会有该模块的数据部分的副本,代码部分是共享的。

共享模块被映射的虚拟地址空间就在上面进程虚拟空间中的 (Memery Mapping部分)

 

最后说一下C程序的入口,main函数是任何C程序必备的函数,它代表整个程序执行的开始(其实有办法在main程序开始前和结束后执行一些想完成的操作,不过这个了解不多,也暂且不管)

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值