冒号和他的学生们
——程序员提高班纪事
18.系统语言
居高者形逸而神劳,处下者形劳而神逸 —《洪应明·菜根谭》
问号忙问:“您打算比较哪些主流语言呢?”
冒号回答:“就谈谈第一堂课提到的最流行的十二种语言吧。按语法特征可将它们分为三类:C族静态语言五种——C、C++、Java、C#和D;非C族静态语言两种——VB和Delphi;动态语言五种——Perl、PHP、Python、Ruby
和JavaScript 。”
叹号表示怀疑:“这么多种语言怎么比较得过来?”
冒号解释:“我们主要比较第一类的C族语言,这些也是今后学习的重点,其他的只是泛泛而谈。”
引号猜测:“因为他们更重要?”
“可以这么说。”冒号直截了当,“毋庸讳言,在当今的主流语言中,C族语言应用范围之广、使用人数之多、影响力之巨都是其他类语言所无法比拟的。它们之间的关系从名字上就能看出:C语言的前身是B语言;其后是C++;Java曾被称为C++++--,意思是在C++上增点东西再减点东西;C#中#就是四个叠起的加号;最后D语言干脆在字母上进行升级。”
句号推断:“B语言、C语言、D语言,下一个该D++、D#或E语言了。”
谁知冒号却说:“E语言已经有了,与Java的语法很像。甚至F语言也有了,但不是C族语言,而是Fortran族的。这不,微软还在.Net平台上推出了F#语言,不过这里的F指的是‘Functional’,即函数式。”
逗号向往着:“不如直接搞个终极的Z语言,成为全世界程序员的唯一指定语言,多省事!”
“这难度不亚于全人类共用一种语言。”冒号笑道,“愿望是美好的,我们还得面对现实。不扯远了,你们先谈谈一下这些C族语言各自的特点吧。”
众人心想:老冒怎么跟国足一个毛病,老喜欢回传,就是不直接射门,真是急煞人也!
问号拣了个软柿子:“C语言是C族老大,又是唯一的纯过程式语言,当然与众不同啦。”
引号一板一眼:“C++在过程式的基础上又引入对象式和泛型式,同时保持了C的高效性和底层开发能力。”
逗号接道:“Java既继承了C++的优点,又克服了C++的复杂性,虽然底层开发能力有所减弱,但具备平台无关性。”
句号不紧不慢:“C#兼具C++与Java各自的优点,但效率上不如C++,跨平台方面不如Java。”
叹号后悔嘴慢:“剩下一个最陌生的D语言,在第一堂课之前还真没听说过,怎么挤上主流语言位置的?我想。。。呃,它总该比C++要高级吧。”
冒号评价:“各位谈得虽然简单了些,也算八九不离十吧。下面我稍微展开些来讲。”
此时众人有一个共同的愿望,希望老冒这次能痛快地单刀赴会、直捣黄龙。
冒号似乎看出大家的心思,开始口若悬河:“关于C语言,前面多次提到。这是一把历久弥新的宝剑,一旦出鞘,依旧寒光逼人,锋利无俦。有了它,便如战将有了佩剑,平添一分独闯敌营的胆气。尽管以现代的眼光来看,它存在不少缺点,但即使抛开C语言辉煌的历史不谈,单就其以如此高龄在诸多后辈冲击之下仍屹立不倒而论,让人无法对其多加苛求。”
逗号提出异议:“但语言不是让人崇拜的,而是让人运用的。一门语言无论过去如何荣光,如果不适应现代发展趋势,还是可能被淘汰。”
“说得非常好!”冒号竟然鼓起掌来,“迄今为止本课堂对于具体知识的讲授并不多,但一直提倡独立思考,不要盲从权威。如果你们能做到这一点,本班的目标也就实现了一半。回头再说说C语言,它源自Unix操作系统的开发,以其良好的抽象性和可移植性取代了汇编语言作为系统开发语言。因其简洁实用、灵活高效,很快从系统领域发展到其他领域而成为通用语言。随着新兴语言的崛起以及硬件性能的大幅提高,C语言的缺点也日益显著:过于宽松的类型检查、容易出错的内存管理、相对贫乏的语言特征等等。虽然自身还在发展,它的市场份额日益减少乃不争的事实。但在相当长的时间内,它在其所擅长的领域里仍会占举足轻重的一席之地。如果C能借鉴C++的命名空间、重载、异常处理和STL等非OO的特征,它的生命力绝不会比任何OOP语言弱。“
引号咨询道:“关于C语言的学习,您有何建议?”
“精读K&R的《The C Programming Language》,此书不过二百页,堪称C语言的剑诀。其中的R即Dennis
Ritchie,是C的创造者,同时也是Unix的缔造者之一,是真正的大师。如今的大师,同博士、教授、院士等头衔一样,严重地通货膨胀了。”冒号不无感慨。
问号尖锐地问:“C++既保持了C的底层开发能力,又引入了OOP,C的处境想必更加艰难吧?”
冒号坦承:“这是不假。C++成功的一个重要因素是对C语言的兼容,由此吸引了大批的C程序员。但这不是没有代价的,C++在兼容C的同时也保留了C的许多缺陷。Java成功的地方有很多,一个不容忽视的因素是它彻底摆脱了与C兼容的桎梏。由于C++对C的改革不彻底,又过于庞杂,并且效率上不如C,这使得C仍有其生存空间。略有讽刺意味的是,对C++批判最激烈的往往来自C的社区,比如Linux之父Linus Torvalds就曾激烈地批判过C++。”
“Linus?那可是我的偶像呢!”叹号惊讶道。
冒号劝诫:“如果你因为是他的粉丝而后悔学C++,那就是为他人的偏执买单,不管那人名气有多大。”
句号指出:“C++最为人诟病的地方有:语法过于复杂,学习曲线陡、开发效率低;支持的范式过多;OOP不彻底;自省(Reflection)功能不足;支持指针操作导致安全隐患;没有自动垃圾回收,容易内存泄漏;没有线程支持;没有丰富的标准库支持图形界面、网络编程等。”
“罪状不少哇!这些说法都有一定道理,但也有失公允。且听我一一道来。”冒号当起了辩护律师,“C++过于复杂这点没错,Stroustrup说过一句耐人寻味的话:一种语言不复杂是因为不成熟。成人肯定比儿童复杂,因为他要承担更大的责任。大家不妨看看Java从1.0到6.0的发展过程,是否应证了这一点?当然C++的复杂度的确高于其他语言,但如果不执着于奇技淫巧,它绝非高不可攀。C++的开发效率相比Java与C#,差距主要在两个方面:一是标准库不够完善,二是需要手工回收垃圾。关于前者,的确是C++的一大软肋,标准库竟然连企业应用中最常用的图形界面、网络编程、数据库处理等都不能涵盖,严重障碍了生产力。其实C++也有苦衷,不像Java和C#那样有大公司的鼎力支持,只靠效率极为低下的标准委员会来维护。98年的一个标准直到03年还在修订,下一个标准至少要到09年。连Stroustrup都在哭穷,说没有足够的人和时间来开发标准库,可为何广受赞誉的Boost库至今仍徘徊在标准门外?考虑到Boost的创办人大多出自标准委员会,其他无此背景的类库恐怕更难登C++之堂了。相比之下D语言更惨,虽然天生丽质,苦无豪门青睐,只好一直待字闺中。”
叹号感慨:“金钱才是技术的最大推动力啊!”
“话糙理不糙。”冒号也很无奈,“此外,C++不支持自动垃圾回收,是因为Stroustrup固执地认为这该由library来支持。一方面,C++主张RAII(Resource
Acquisition Is Initialization)原则,通过析构函数(destructor)或智能指针(smart pointer)能在大多数情况下有效地解决内存释放问题;另一方面,尽管自动垃圾回收机制逐渐为大众接受——据说C++0x也将部分地支持它——但这种机制也存在缺陷。比如一个Java程序如果在某一时段极耗内存,由于自动垃圾回收的不定时性,不能保证及时清理内存,可能会抛出OutOfMemoryError。另外,自动垃圾回收机制并不能完全避免内存泄漏问题,Java程序的内存泄漏可能会比C++的更多,因为C++程序员对此更有戒心。”
问号直奔要害:“您如何看待C与C++中的指针?”
冒号欣然接招:“指针是C与C++最大的特色,其他语言要么不支持,要么支持得有限。C与C++可以说是成也指针,败也指针。用得好可以是削铁如泥的神兵利器,用得不好则可能是自我毁灭的罪恶渊薮。但由于二者定位于系统语言,而指针对于底层操作是必不可少的。同样道理,二者的数据类型的转换比其他静态类型语言更自由,也是源出于此。”
句号总结:“能力越大,责任越大,风险越大。”
“正是此意!”冒号重重地敲了一下桌子,“此话既适用于编程语言,也适用于程序员。至于C++缺少对自省功能的支持,也是因为追求效率,不愿在元数据上花时间和空间。说到C++支持的范式过多,程序员过于自由,代码不标准难维护,这就如同埋怨餐馆提供的菜式过多以致难以摆出一桌酒席一样可笑。最后,指责C++不是100%OOP的说法更是荒谬之极。OOP又不是金子,含量越高越好。试图把一切都装进OOP的箱子里的想法无异于削足适履。典型的如Java中的Math类,逻辑上压根儿就不存在什么Math对象,清一色的static方法和常量就是最好的讽刺。在C++中只要在math的namespace中定义一些自由函数就可以了,自然而简洁。”
引号发觉:“您好像把对C++所有的责难都化解了。”
“可恨之人必有可怜之处嘛。”冒号俗语反用,“其实C++仍有不少亟待改进之处,D语言就是很好的启示。D语言的提供了可控制的垃圾回收器;支持动态数组(dynamic
array);支持契约式设计(design by contract);废除了C与C++ 令人头痛的头文件(header
file)等等。这些都是C++程序员梦寐以求的特征。”
逗号很奇怪:“为什么D语言名气这么小?”
句号吟道:“千里马常有,伯乐不常有,大腕伯乐更稀有。”
众乐。
冒号结语:“C与C++同为系统语言,决定了它们的理念是:优化机器的时间而不是人的时间,优化机器的记忆而不是人的记忆;假设编译器是愚蠢的而程序员是聪明的,因此赋予程序员更多的权利、义务与责任。无视这种背景和理念而去与其他语言相较,必不着筋节。需要强调的是,常见的‘C/C++’的说法很不科学。C与C++虽有千丝万缕的联系,但一个简单,一个复杂;一个纯过程式,一个集过程式、对象式、泛型式和元编程于一体。貌合神离,不宜混为一谈。”
叹号一个问题憋了半天,不吐不快:“我有一个问题:如今电脑性能这么高,C与C++如此强调运行效率还有必要吗?”
“绝对有必要!”冒号斩钉截铁,“其一、纵向看,用户的耐心与电脑的速度成反比,早年一个386人们就满足了,如今却忍受不了586;其二、横向比,相对缓慢的系统竞争力也低;其三、在一些领域如人工智能方面,普通电脑的速度还远远不能满足要求,超级计算机的存在就是明证;其四、仍有些程序跑在资源有限的机器上,比如嵌入式系统。”
引号再次要求:“能推荐一些C++方面的书吗?”
冒号直言:“学好C一本书足矣,学好C++即使推荐十本仍有遗珠之憾。可以说C++是苦了编程者,甜了著书人。开个小书单:初级——《C++
Primer》和《Thinking in C++》;中级——《The C++ Programming
Language》和《Effective C++》系列;高级——《The C++ In-Depth》系列。这里还要特别推荐一下《The Design and
Evolution of C++》,从中你可以看到 C++的设计和演变的来龙去脉,极具启发性。C++是匹无辔无鞍的野马,看似桀骜不驯,若能顺性而御,必能足踏飞燕,行千里而不劳。”