程序设计语言概述_c语言程序设计基本概念

程序设计语言概述_c语言程序设计基本概念许多各位转载请注明出处。http://www.cnblogs.com/hetao/archive/2010/03/17/1688388.html最近于2010年3月18日日修改。阅读指引读懂此文,需要

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

许多各位转载请注明出处。
http://www.cnblogs.com/hetao/archive/2010/03/17/1688388.html 
最近于2010年3月18日日修改。

阅读指引

读懂此文,需要以下基础

1.        至少写过1000行的代码。

2.        汇编基础(静态数据段,代码段,堆栈段)

有以下或者类似知识就更好了

1.        C语言编译C++对象模型,MFC反射的实现。

2.        JAVA的动态编译器原理,

3.        使用过javascriptPythonPHP经历过其代码和类型运行时自由性

4.        计算机组成原理

 —— 一些问题

1.        程序设计语言的目的是什么?

2.        为什么大多数语言有控制流?逐行执行+跳转。这与我们的需求差很远(例如一个教务管理系统。)

3.        为什么类型申明C语言中要与控制流隔离开来?

4.        现在主流语言最基本的元素是?

5.        有没有语言它的类型结构,在运行时也可以改变?

动态性?

什么是动态性?

1.        编译后确定了什么信息之后不再改变

2.        运行时可以改变、添加什么。

3.        运行时是否保存着类型信息。

程序中的信息分为几类?

1.        数据信息

a)       编译时Meta-Data元数据(类型框架,空间占用

b)       运行时Meta-Data元数据(继承体系用于new或者反射特别区别编译与运行的Meta-Data的不同。

c)        堆栈段中地址偏移C++switch case不能声明变量。共享内存

d)       静态段中地址

2.        指令信息

a)       代码段(动态性需要操作系统或者虚拟机支持例如动态链接库,动态类加载,lisp语言自生成代码)

语言举例

汇编语言

汇编语言没有动态性吗?

没有

首先寄存器数据段、堆栈代码段完全由程序员控制完完全全是写死了的。

然后根据冯诺伊曼的规则;取指令,执行,取指令,执行……

既然都有数据段了,还要堆栈段来做什么?这不是多余

一开始没有堆栈,直到60年代出现了module模块,才有了堆栈

汇编中的模块叫子程序,不过仍旧靠程序员全权控制

堆栈和模块化的优点有?

1.        递归

2.        功能分离到模块,可复用

3.        封装作用域

堆栈和模块化的缺点有?

1.        时间上:保存现场、还原现场的代价另,高级语言编译消除尾递归节约部分成本)

2.        空间上:爆栈的危险

C语言

C语言比起汇编多了什么东西?

1.        编译器

2.        表达式(相比汇编,可以处理多个操作数了。)

3.        函数与模块{}·模块化,栈操作无需程序员完成

4.        类型(原子类型结构类型数组指针

5.        头文件,库

总之,C语言并没有比汇编多了新的特性,它只是把汇编的繁琐操作抽象出来,让编译器完成,减轻程序员负担

编译器的作用是?(减少程序员负担)

1.        解析表达式,控制流(汇编中指令只有1-3个操作数,而表达式可以多个操作数

2.        模块和函数的抽象完成堆栈中保存恢复现场的工作)

3.        类型变量的管理(所有变量被替换成直接访问的地址,最快的访问速率

4.        代码优化

变量是替换成可以直接访问地址的?

a)       编译时Meta-Datastruct成员数组的长度,以便替换到指令流;只在编译器中维护,编译结束后丢弃

b)       计算出每个变量相对于该模块的偏移(一旦算出该偏移地址,将固定在执行码中,无法改变;就是说编译完成后,所有变量的偏移地址都固定下来。)

c)        对变量的存储进行管理(所有的变量/内存地址的布置,都是在编译时确定的;也就是说,可执行码中没有类型信息,只有地址,任何数据都是地址来操作,完全和汇编类似。至于寄存器的安排,那是更下一层的类似缓存策略算法的结果。

编译出来的执行码与汇编的执行码特征的区别吗?

没有。特别是在编译器优化之后。

无法通过执行码区分汇编和C程序。

打个比方,一只程序猫在黑布笼子里,在里面喵喵的叫,无法通过它的叫声来判断它是汇编猫还是“C语言猫

从效率上来讲,C的多余代价在哪里?

1.        编译的时间

2.        模块的堆栈操作

总之,经过优化的C程序执行码与汇编效率几乎相同。

因为从理论上来说,C并没有引入运行时的新机制

我理解的C语言只是一种汇编的宏而已。

 

C++语言(推荐《深度探索C++对象模型》)

C++语言比C语言多了什么?

1.        成员函数

2.        类型继承体系

3.        虚函数、虚继承

4.        模板

5.        涉及到了多种编程范型开始抽象,语言逐渐开始脱离冯氏结构。

其中,面向对象的思想,让程序与现实事物的关系更加紧密。

程序设计的负担,也因为OO与设计模式的流行,而变得轻松。

编程范型是什么?

就是一套指导思想行为准则。

例如,C是过程式,Haskell是函数式,JAVA是面向对象,Python简单的大杂烩,shell是调用命令的lua是调用c程序的,PHP是写页面的,ProLog是线性逻辑推理的。

再例如,UML是描述规格specification的,XML是存储数据的。

再例如,CSS是描述网页表现的,HTML是描述网页内容的。

javascript比较神奇,不敢说

C++有什么编程范型?

1.        过程式(使用STLC语言编程)

2.        ADT式(自定义抽象数据类型,继承;但是不用new,不用virtual;拷贝构造

3.        面向对象式(使用new,使用virtual,需要指针或引用;实现多态。

C++编译器是怎样实现的?

C++开始有一个叫做cfront的编译器,即把C++语言先翻译成C语言

然后再用C编译器来编译C的编译器并不知道此段代码是来自C++还是C

C++语言特性分别是怎样实现?简单说。

1.        成员变量:和C语言的struct 类似,最后也会被直接替换成地址,便于高效访问

2.        成员函数使用特殊函数名编码方案翻译成C函数,并添加this指针作参数(如___clsA12345func001(…,clsA *this))

3.        类型继承体系通过C++编译时Meta-Data来实现。编译时编译器是知道类型信息继承体系的,但是编译成C语言后就丧失了此类型信息

4.        虚函数、虚继承为了支持多态,这也是面向对象最重要的特性,使用了虚函数表和虚基类表。注意,运行时多态是通过运行时查表实现稍后详细说。

5.        模板:通过代码复制的方式实现。每次编译都需要重新编译,不能编成库文件直接使用。

C++编译器的准则与virtual机制?

1.        首先,C++的编译准则,希望做到与C一样的效率。希望做到以下:

a)       没有运行时调用间接性。任何数据在运行时都是一个地址直接就访问到。

b)       没有运行时的Meta-Data。无需通过Meta-Data来访问某个复杂的类层次。

c)        所有的数据都希望用Cstruct来实现,即在编译时就确定好对象及其成员地址。

2.        以上,在过程式范型,与ADT范型中都是成立的。

3.        但是,面向对象范型中,渴望做到:

a)       需要维系着同一个继承体系成员结构的一致性,只有这样,才能保证运行时的多态性。即希望通过同一个地址,访问到父类或者子类相同数据成员、函数成员,而不在乎具体对象的是父类还是子类。

C++virtual机制如何实现的?

b)       虚函数

i.          虚函数,运行时,每个有虚函数的类型(哪怕是子类)都维持着一个虚函数表,这已经是运行时的Meta-Data通过查表,即可找到对象自己虚函数

ii.         例如下图中clone肯定是object.__vptr__Base->#3(),无论具体的对象

iii.        程序设计语言概述_c语言程序设计基本概念

c)        多重继承

i.          如何处理后继的base基类?由编译器判断指针类型并加上相应的偏移

d)       虚继承

i.          添加一个虚基类指针,指向共享部分

ii.         程序设计语言概述_c语言程序设计基本概念

iii.        这样的缺点有两个

1.        虚基类的子类都要背负一个基类指针指向共享部分。如果继承了多个虚基类,还需要多个这样的指针。(Microsoft的解决方法是增加一个虚基类表,类似于虚函数表。)

2.        继承链条的增加,会导致间接访问的层次增加。例如两个菱形继承的串联。

头文件,库,源代码跨平台

1.        C++确实在源代码的层次是可能跨平台的。

2.        也可以通过相同的头文件去访问不同平台的库。

3.        但是,不同操作系统中的不同的API大大增加了跨平台的难度

4.        跨平台的责任留给了程序员(充斥着大量宏的C++跨平台代码确实让人头疼。)

5.        编译器面对不同的系统也不敢作为,它只是负责编译源代码,链接。

如何使用C++才能保证其高效性能?

1.        有额外负担的机制虚函数,虚继承,拷贝构造。

2.        一次虚函数,多了一次指针寻址的效率损失,并且相对于inline内联(另,inline是编译器优化的重头,还损失了保存和恢复现场的效率。

3.        用一次虚继承多一次指针寻址的效率损失(另,虚基类没有成员变量没有虚函数的时候会被优化。这也是JAVA可以多重继承接口interface的原因。)

4.        不要使用virtual在复杂多继承,深层次继承中。

5.        编译速度会较慢:virtual机制会使编译器处理更多的Meta-Data

JAVA语言(推荐本地Java代码的静态编译和动态编译问题

JAVA语言比C++语言多了什么?

1.        虚拟机

a)       跨平台

b)       动态编译

c)    动态特性

2.        没有指针

3.        没有类的多继承,有接口的多继承。

4.        统一的库

从编译来说,JAVAC++迈出了一大步。

 它的跨平台特性和运行时的灵活性JAVA自己以及未来语言提供了很多可能性。

虚拟机的好处有什么?

1.        跨平台:在OS与字节码间隔了一层。实现了程序员无负担的跨平台。

2.        动态编译:许多信息不必在编译后确定,为动态特性提供可能,稍后详细说。

3.     运行时维护着类型信息,甚至可以加载新的类型。(CORBRA依赖这个实现。)

JAVA编译执行的过程是怎样的?                           

1.        编译后产生一个基于堆栈的字节码

2.        JRE在不同的OS上提供支持

3.        起初的JRE是解释执行的,效率低下。

a)       获取待执行的下一个字节码。

b)       解码。

c)        从操作数堆栈获取所需的操作数。

d)       按照 JVM 规范执行操作。

e)       将结果写回堆栈。

JAVA是如何解决执行效率低下的问题呢?

使用JITJust-in-time)编译器进行动态编译。

程序设计语言概述_c语言程序设计基本概念

JITJust-in-time是怎样运行的呢?如何解决了效率的问题?             

如上图:

1.        每次按照一个function来编译。转成中间表示,并优化其效率,再生成可执行码。

2.        编译器的编译线程和执行线程是分开的,应用程序不会等待编译的执行。

3.        分析框架Profiler会观察程序行为,对频繁执行的function进一步优化(例如function内部对象维持一个池不必每次生成。)

动态编译的优点有什么?

可以根据程序的行为,优化其代码

1.        例如频繁执行的function——热方法

2.        例如arrayCopy方法如果每次都拷贝大段内存在指令中有特别指令可以加速

3.        例如类层次结构,多态的优化。大多数虚调用都有其固定的一个目标,JIT因此生成的直接调用代码比虚调用代码的效率会更高。

动态编译的缺点有什么?

1.        大量的初始编译会影响程序启动时间。

2.        运行时候的编译,行为分析都需要花费时间。

3.        运行效率达到稳定需要时间

4.        实时GUI型的程序不能忍受动态编译“GC”带来的延迟。

JAVA如何解决实时的需求?

使用AOTAhead-of-time编译器:预先编译成为可执行码。

AOTAhead-of-time的缺点

对于一些动态特性的支持效率低下

1.        反射机制

2.        运行时类加载

JITAOT的对比

程序设计语言概述_c语言程序设计基本概念程序设计语言概述_c语言程序设计基本概念

总体来说,JAVA适合怎样的应用呢?

JAVA比较时候需要长期运行的应用,例如Web服务器,Daemon服务。

函数式语言

函数式语言通常有哪些呢?

1.        函数式语言

a)       Lisp

b)       Scheme

c)        Haskell(纯函数式)

d)       F#

2.        包含了函数式特性的语言

a)       Python

b)       Javascript

c)        JAVA

d)       C?

函数式语言有哪些特性?

1.        函数无副作用,只对输入输出有作用

2.        高阶函数,lamda演算(这个C函数指针,但是它是高阶的,即返回值可能也是函数)

3.        没有过程,类似规格说明语法,更容易理解,自解释

4.        基于list的编程函数更通用

5.        惰性计算(这个很像树形DP”

6.        有对应的数学形式化表达有可能证明其正确性。(最终目标可能是保证程序没有bug


总的来说,函数式语言,向着更抽象迈了一大步,几乎与冯诺伊曼体系断绝了关系。

函数式语言的劣势?

1.        效率不高(因为其抽象远离冯诺伊曼体系

2.        平台以及开发环境都比较简单

3.        缺少推广,应用不广泛

逻辑程序设计

ProLog语言,线性逻辑。人工智能语言。没有接触过。

动态性有哪些呢?

1.        多态性:运行时根据具体对象来访问属于它的方法。(而不理会指针的类型。)

2.        反射:运行时维系着类型结构Meta-Data

3.        运行时类加载:运行后再次加载新的数据类型和指令流

4.        动态链接:OS根据按需链接库文件。

编译语言 和 解释语言

语言本身并没有编译类型或者解释类型。(例如:JAVA也可以静态编译后成可执行码。)

只有少数运行时特性是依赖于解释型的。可能需要运行环境的支持。)

为什么解释语言都需要虚拟机或者运行环境支持?

动态编译,运行时Meta-Data的保存,这些功能对于每个程序都是一致的

所以把它们分离开来,不必每个程序植入这些代码。

非脚本语言 和 脚本语言

脚本语言,我理解是负责调度其他代码的语言。

例如shell脚本(调用命令)lua(调用C

但是也不确定,例如Python

跨平台

跨平台分为哪些层次?

1.        源码跨平台(CC++,但是因为系统调用接口不同,程序员负担太大,但是汇编却不是

2.        执行码跨平台JAVA,有些语言直接从源码解释执行,例如JavascriptPHP

 

发展历史(推荐近看图灵碗 (从苏黎世到巴黎)

学术上有哪些实验性语言

1.        Fortran

2.        ALGOL58

3.        ALGOL60

4.        Lisp

5.        smalltalk

常用语言

过程式:CALGOLPascal

面向对象式:C++smalltalkJAVA,Delphi

函数式:LispSchemeHaskell

逻辑式:Prolog

脚本?PHPPythonRuby

存储描述信息:XML,CSS,HTML

结语

程序设计语言的目的是什么?

1.        控制数据

2.        控制指令流

为什么大多数语言有控制流?逐行执行+跳转。这与我们的需求差很远(例如一个教务管理系统。)

逐行执行,很大程度是起源于冯诺依曼体系结构。

为什么类型申明在C语言中要与控制流隔离开来?

因为在编译时,具体的类型信息,要转化成地址偏移,然后替换控制流中的类型变量

现在主流语言最基本的元素是?

控制流 与 类型系统。

有没有语言它的类型结构,在运行时也可以改变?

Javascript只有对象没有类,使用prototype的方式继承,运行时给某个对象添加新的数据成员。没有类型体系。

许多后来的语言在运行时都保存着类型信息的,例如PythonJAVA

 总结

控制流——指令流
类型系统——为了计算出变量地址信息
区分运行时的Meta-Data与编译时的Meta-Data
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/168096.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • FAE新手上路_ra上路

    FAE新手上路_ra上路2018年夏天,因为犹豫,最终放弃了一家中意的公司,选择继续留在原公司,这是我到目前为止进入互联网行业做的最错误的决定,网上无数血的教训,同事委婉的劝告,都没改变我跟随新领导的“决心”,另外自己也没有做好换一个新环境的准备,所以就留下来了,换来的是兑现不了的大饼和离职时差点闹开的不堪经历,过去的是是非非我就不作评价了,只是以我的之前的经历告诫各位,一、不要去外包公司。二、提了离职,绝…

    2022年10月28日
  • 实现labelme批量json_to_dataset方法

    实现labelme批量json_to_dataset方法labelme可以帮助我们快速的实现Mask-RCNN中数据集json文件的生成,然而还需要我们进一步的将json转成dataset,可以直接在cmd中执行labelme_json_to_dataset.exeC:\Users\Administrator\Desktop\total\1.json(路径),但是这个过程需要我们一个json文件的生成,过程很慢。一、打开abelm…

  • 小米手机解BL锁教程

    小米手机解BL锁教程1.找到设置,找到我的设备2.点击全部参数,点miui版本,点3下。3.返回,找到更多设置4.找到开发者选项5.找到设备定状态6.绑定账号和设备,关机,按开键加音量减,进去fast模式,链接电脑。7. 电脑打开下载解锁工具:点击链接下载将解锁工具解压缩,点击unlock.exe。7.解锁工具里登入可解锁的小米账号,同时将手机进入fastboot模式(关机状态下长按音量下键和电源键),用数据线连接电脑,提示已连接手机即可,若没有驱动点击图标安装即可。8.设备已解锁-解锁成功

  • cmd 里面运行git提示“不是内部或外部命令,也不是可运行的程序”的解决办法…「建议收藏」

    cmd 里面运行git提示“不是内部或外部命令,也不是可运行的程序”的解决办法…

  • MySql的root密码忘记该怎么找回

    MySql的root密码忘记该怎么找回Windows下如果MySQL密码忘记了root密码导致无法登录,如下图所示,这个时候怎么办,只能重置root密码了。1.打开任务管理器查看MySql服务是否启动,如果已启动则先将其停止2.找到MySql目录下的my.ini文件3.打开该文件,找到里面的[mysqld],然后在这个下面添加skip-grant-tables,添加完后保存文件4.重新进到任务管理器将…

  • 互联网测试面试题及答案(软件测试面试题及答案2019)

    很多软件测试工程师在面试互联网企业的时候都会遇到考官给的几道面试题,这也反应了测试工程师对企业的重要性,今天传智播客整理了一份2019年的互联网企业软件测试面试题,希望能帮助到大家。2019年互联网企业软件测试面试题(常考)1、什么是兼容性测试?答:兼容性测试是检查软件在不同软件平台,硬件平台上是否可以正常运行的测试。主要查看软件在不同操作系统、浏览器、数据库中运行是否正常。2、你能不能…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号