第1章 启蒙
1.5. 什么是编程语言
程序是指令按照一定的逻辑组合而成。在游戏中,双方使用的是“自然语言”来表达“指令”。如果游戏双方是聋哑人,那么你用嘴巴说的那套指令就玩不转了——计算机聋不聋不好说,但当我们要对计算机下达指令,人类的那一套得天独厚的,具有悠久历史的自然语言,肯定玩不转了。怎么办?
解决这一问题所要做的第一件事就是:制定“机器语言”——机器有了语言,我们就可以……
等等,机器,没有生命的东西!小猫小狗有语言倒可以接受,机器也有语言,还要我们去学习,这似乎有点亵渎人类的尊严。得把这个结解开,不然部分自尊心特别的学生,可能从此产生心理障碍,无法继续学习编程。
首先一点,语言肯定不仅仅代表有声音的内容,英语、汉语等,说出来是口头语言,写在纸上是文字语言。哑语则是一些手势的所表达符号。
前面我们谈到“指令”,其实语言就是表达那些指令的一套交流符号。只要交流的双方都能正确理解这套符号即可。用人类的语言表达计算机的“指令”,当然绰绰有 余,但关键是机器无法理解。所以让我们且低下高贵的头颅,寻找一套计算机最容易“看明白”的符号,拿它作为计算机的语言,然后我们再去学习它。
让人去学习本适于机器的语言,伤自尊倒是一回事,关键机器语言人类记忆起来很头痛——这一点我们后面就会讲到——还好,事情并未完结:其实,只要有几位先知 先觉的计算机科学家,掌握了机器语言,他们就以此和机器交流,然后就可以慢慢地“教”会计算机“懂得”一些更接近一点人类的新语言。这样,我们这些普通用 户们,就可以直接学习新的编程语言了。
1.5.1. 机器语言
什么样语言,可以让计算机一看就能明白呢?
直至今天,我们所用的计算机,叫做“电子计算机”,因为它们的重要组成,仍然是电子元器件。以我超级贫匮的电子方面的知识,我还是能讲出常见的电子元器件有“电阻”和“电容”;其中有关电阻,中学里学过什么“当电压一定时,通过导体的电流与它的阻成反比”
——头好大啊!难道为了学习编程,我们就不得不去学习复杂电子电路的知识?还好,这一切都是杞人忧天。
中国古人曾经发明过算盘,算盘分为上下两个区,其中上区的一颗珠表示5,而下区则一颗珠表示1。发明电子计算机的先哲们(当然包括冯·诺依曼同志),同样聪明,他们找到的,适用于电子计算机的基本符号居然是:“通电”和“断电”。
不过,我们也有疑问,就用“通”、“断”两种状态表达,有些浪费电子元件的表达能力吧?为什么不用电阻或电压值来表达呢?比如,1伏表示数字1,2伏表示数字2,3伏表示数字3……
只采用“通电”、“断电”两种状态作为计算机语言的基本符号,主要出于“精确表达”这一需求。既然名字都叫“计算机”了,如果这家伙它计算不精确,那它再 “能说会道”有什么用?用电压、电阻或电流的值作为语言的符号的话,第一个问题就是精度上难以实现,想想你家的灯泡,给220伏它亮,给它221或219 伏,都是差不多亮,别说人看不出来,拿仪表量,指针也是晃来晃去,因为现实生活中我们难以精确控制电压值。
1.5.2. 机器语言的“字母”
科学家用“0”和“1”,来表达“通电”或“断电”。不过它们仅仅是计算机语言的“基本符号”。英语中有26个字母,单词由26个字母组成,然后再由单词组 成语句。我们也可以机器语言有,并且仅有两个字母,那就是“通电”和“断电”,为了表达更简捷一点,我们今后就说成是“0”和“1”(至于0是表示通电还 是断电,我们不去关心了)。
〖轻松一刻〗:用机器语言写份情书吧
哈哈,没想到吧,刚才谁吓唬俺们说机器语言不好学?我看它至少比英语容易13倍。让我们现学现用一下。你有男/女朋友吗?首先你们碰个面,一起约定一些“机器指令”的表示方法,比如:
0 :你
1 :我
10 :老的
11 :地方、场所
100 :相见
101 :想念
111 :很、非常、那是相当的
1000 :今天
1001 :晚上
1011 :七点钟
1111 : 亲爱的
今后,你们可以用自定义的计算机机器语言来交流了。比如,这是一封信:
“1111: 1 111 101 0! 1000 1001 1011 10 11 100。”
1.5.3. 二进制(基础)
人类有10个指头,所以人类采用十进制。电子元件有两个最稳定状态,“通电、断电”,所以电子计算机采用了二进制。
十进制中,我们用0~9这十个数字来表达所有的数字,换成二进制,就只能用“0”和“1”来表达所有数字了,在小学老师就教我们 “逢十进1” ,所以我们知道9+1=10;那么,在二进制的世界中,1+1=10。二进制中的“10”(读成壹零),就是十进制中的2。
用这种方法,就可以用0和1来表达所有数字。但事实上计算机中所有数据最终都是由0和1表达。只不过根据严格的上下文,它们并不一定代表数字。相反,它们可能是一首MP3,一张相片,一封email信件的内容。比如“250610”这串数值,根据上下文的不同,可以被解释成数字“二十五万零六百一十”,也可 以被当成是山东省某个地方的邮政编码,甚至你可以认为它是一段简谱呢。
那么,用只有0和1这两个“字母”的机器语言来编程的话,当然也就是满纸的0和1了——最早的程序确实是写在纸上的,只不过比我们想象的还要有趣,纸是长长的纸带, 而0或1则用画圈圈表示,一圈两圈三圈,有圈的地方估计是表示1?然后交给负责打孔的助手,有圈的地方打上一个孔。当程序需要被执行时,就将纸带塞给机器。机器要实现读懂这些孔,确实不复杂,比如可以用光线来测试,光线能穿过去的地方,应该是1。
1.5.4. 汇编语言
还记得我们用二进制写的那份情书吗?
“1111: 1 111 101 01 1000 1001 1011 10 11 100。”
我保守地认为,使用这样的语言写情书,对于增进你们之间的爱意,恐怕帮助不大,但它肯定有利信件内容的保密,同时也利于恋爱两方锻炼记忆力。
纯粹的机器语言实在太难于记忆及辨认了。所以,先哲们立即想到要为它们制定一些助记符。因为计算机是西方人发明的(并不是唯一原因),所以助记符就是一些简短英文字母组合,这些助记符及相应的语法规则,就称为“汇编语言”。
比如,我们要实现这样一段功能:已知b等于1;c等于2;计算b + c值,并将该值赋给a 。那么,用二进制机器语言来表达,可能如下。
10001010 01010101 11000100
00000011 01010101 11000000
10001001 01010101 11001000
用汇编语言来写,则可能如下:
mov edx,[ebp-0x3c]
add edx,[ebp-0x40]
mov [ebp-0x38],edx
汇编语言比机器语言稍稍“人性化”了一点,但仍然不好记忆,二者没有本质的区别,仅是一种简单的翻译,很多时候,我们把汇编语言与机器语言等同视之。
〖轻松一刻〗:汇编语言是“江湖”中的老大
汇编语言是编程界中的“老大”。当初的一片天下是他所打下的,但发展到今天,他已经很少在江湖上露脸了,然而,在一些最困难和紧要的关头,还是要汇编语言出手,其它语言都失灵。
“老大”的做事风格是“密不透风”。有时就算是一件很小的事,“老大”也会使数百行的代码进行攻击。有些人会觉得这种做事风格太繁琐了;然而真正理解“老大”的人,会发现那数百行招式,招招凌厉,直击要害,再一细看,竟然没有哪一招是多余的。
事实上,要想理解汇编语言,最重要的一点就是理解你所处的江湖环境,也就是机器本身,直到你真正理解:“汇编即机器,机器即汇编”,老大与江湖,早就浑然一体,只要你理解并做到这一点,你也可以是“老大”。
1.5.5. 高级语言
汇编语言和机器语言虽然很难读、难写、难以记忆,但它们不需要额外编译,代码效率高,占用内存少,这相当符合当时计算机的存储器昂贵,处理器功能有限等硬件特点。从这点上讲,机器语言是让人类痛苦,让机器舒服的语言。
我们说过,先哲们迁就一下计算机,发明了“机器语言”,然后就应该“教”会计算机另一些比较靠近人类思维的新语言。
事实正是如此,有了机器语言以后不久,先哲们就开始考虑,如何实现一些让人类用起来舒服点的编程语言了。这些语言当然是在语法组织尽量符合人类的良好思维习惯,不过反过来它们肯定不能被称为“机器语言”,因为机器不可能直接理解这些语言。解决的方法有几个,其中最典型的方法称为“编译”:需要用机器语言先写一个程序,称为“编译器程序”,编译器读入新语言写成的代码,将其转换成机器语言。后来,这个编译器程序也可以用“高级语言”写成。
为了区别于“机器语言”,这些语言被称为“高级语言”。高级语言“高级”在哪里呢?我想,可能是指它们总是尽量接近“高级动物”——人——的思维方式这一点吧?
现阶段,这里所说的人类的“思维方式”,主流是“面向过程”和“面向对象”两种方式。
- 面向过程
日常生活中最常用到的问题解决思路:要完成一件事,先把它分解成多件小事,也就是:把一个相对大的“过程”,拆分出存在时序关系的多个小“过程”。
举个实例。现在一位家族主妇想做一道菜, 那可能就要分成:备菜、炒菜、上桌……等等过程。而其中“备菜”过程,可又以细分为买菜、切菜等等。(坦白承认,我对该业务的过程并不熟悉)
对应到编程语言,通常用函数/function代表过程(也有的语言就直接叫成“过程/procedure”)。 - 面向对象
面向过程的思路很直观,但当问题的复杂度太高时,我们就不太可能很有条理地将理出到底需要多少个子过程——比如让你担当一届奥运会的开幕式导演,这时我们就不应该试图直接把事情从大到小分到很细。
面向对象是在面对复杂问题时,我们首先关注问题将涉及到哪些事物,然后把各个不同类型的事物,当作基本单位,定义它们各自的数据与行为能力,以及不同事物之间的相互关系。
“过程”在“面向对象”的解决思路中依然存在,也依然重要。类似导演在拍电影,剧情就是一部电影的主过程,但是电影的拍摄过程并不按照剧情的发展去拍摄, 复杂的现实情况会左右拍摄次序。比如有时会在一个景区拍完所有和这个景区有关的剧情——此时,“景区”就是一个重要的对象,我们必须围绕这个对象安排事情发展。
----------------------------------------
- C语言
C是“面向过程”语言中的佼佼者,其中最重要一条原因在于它的定位:在“人”与“机器”的两极中,它向“人”这一端迈出了非常优雅的一小步。这是C语言自身的一小步,却是编程史上语言发展的一大步。
在符合“人类”思维这一端,它以“面向过程”为思路,同时提供清晰、简单的语法规则。这一语法规则影响了几个重要的后来者,包括Object C、C++、Java、C#、D等语言。
在 接近“机器”特征这一端——比如当我们需写硬件设备的驱动时——C语言甚至被称为“中级”语言。原因就在于它非常优秀地反映了机器,尤其是“内存”的特 征,因此它保证了与汇编语言的良好兼容,从而代替汇编语言,成为操作系统、编译程序,运行环境的第一语言。C++是直接从C语言发展的,最初C++语言甚 至是“编译”成C语言,然后再编译到机器语言。Java语言则完全运行在在由C/C++所构建出来的“虚拟机器”中。
〖轻松一刻〗:老大的女人——C语言
C语言,一个成熟的女人,一个有地位的女人,一个只描淡妆的女人,一个有着深刻内心的女人,一个处理问题时一针见血,最恨绕弯的女人。
比起汇编老大的满口“行话”,C那样的平易近人,比起晚辈中C++/Java/C#的繁复语法,C那样的简洁明了……然而,C是一把锋利的双刃刀!万不可因为她外表上的简易与亲切,就以为可以随意亲近它。深沉的程序员用C解决难题,浅薄的程序员用C实现自我崩溃。
C语言深刻理解汇编老大的意图,所以往往寥寥数语可以代替老大众多的指令组合。和C++明显不同,它从不试图让编译器帮助寻找代码中潜在错误,它把一切可能和一切责任,都给了爱上她的人。
作为老大的女人,C语言不仅可以直接嵌入汇编语言,而且具备超强的“亲和力”, 如果非要找一门能号令天下,让别的高级语言,都支持它的语言,非C莫属。换句话,如果一门高级语言不能调用C语言的接口,那么它就只能是一门“玩具语言”。
Linux、Windows、MAC 等等操作系统,都主要通过C结合汇编语言写成。其中的缘由,大家可以自行掂量。
江湖规矩:“老大的女人”碰不得——其实不然,只要你低调地苦练成一方老大,那么,你可自豪地说“我只喜欢她”,就像Linus。
-------------------------------------
- C++语言
编程语言的发展,从“低级”向“高级”不断发展。我们已经说过,“低级”指的是“机器”这一端;而“高级”指的是“人类”这一端。那么,这个发展过程中间,一个最原始的推动力,来自语言所要解决的问题,其所在的领域,也在从“机器的问题”不断地发展到“人类社会的问题”。
一台只有硬件的机器,我们称之为“裸机”。这时候普通人几乎没办法使用它,于是需要为它写一套操作系统。在最广泛使用的两个操作系统中:最初名为 “DOS”,现在则名为“Windows”。从名字上,“磁盘操作系统/disk operator system”显然偏向机器,而“‘窗口’操作系统”,既表示这个操作为使用者提供了“窗口”式的图形用户界面,又表示使用者可以通过它,像推开一户窗口 一样,见到一片新的蓝天白云……
从名称,特别是人操作界面上,Windows比DOS 大大地往“人”的方向前进一步,但操作系统的进化仅仅是一个开始,更重要的是应用软件的进化。一个财务人士,希望用软件管理账务;一个人事专员,希望用软件管理档案;一个厂长,希望用软件管理流水线;一个老师,希望用软件来管理学生成绩;一个公务员,希望用软件来提高为人民服务的质量……这时候,软件的关注重心,不是磁盘、内存、CPU之类的硬件,也不是分区、文件、目录等硬件直接相关的数据,而是人类的社会活动中的种种应用。在这种情况下,侧重于“过程管理”、擅长于和硬件打交道的C语言,开始显得有些力不从心,于是许许多多新的,起点更高的编程语言出现了。C++是出现得比较早的此类语言之一,同时也一门被最为广泛使用的“面向对象”的语言。
从名字上看,C++完全从C语言的基础上发展;而在实现上,C++与是对C语言支持得最好的语言,它继承C语言的很多优点,增强编译器的纠错能力,增加对“面向对象”及“泛型”等编程思想的语法支持。
C++语言被广泛地运用在编写大型的应用软件,比如微软的Office、比如Adobe的Photoshop,前者是全世界最为广泛使用的办公软件,也是微软公司最赚钱的软件。后者则是全世界最为广泛使用的图像处理软件,就算你不会美工,但也总该听过“PS高手”这个词吧。另外,由于与C语言的延续性,因此在往 “机器”发展的方向上,C++也在很多场合下代替了C语言的部分功能,比如Windows操作系统的COM组件、Linux操作系统的一些GUI系统,都主要使用C++完成。
之所以我们选择C++作为第一学习语言,主要原因在于我们要通过它来学习“面向对象”的编程思想,然而C++一门集大成者的语言,它不仅支持“面向对象”、也支持 “基于对象”、“面向过程”,以及最为完善的“泛型”编程思想。从这一点和Java、或C#相比,C++不是一门纯正的“面向对象”的编程语言,但这正是C++所追求的:“不同的问题,用不同的方法”。
-------------------------------------
如果您想与我交流,请点击如下链接成为我的好友:
http://student.csdn.net/invite.php?u=112600&c=f635b3cf130f350c