现在的位置: 首页 > 综合 > 正文

程序语言的故事

2013年09月09日 ⁄ 综合 ⁄ 共 3671字 ⁄ 字号 评论关闭

 程序语言与自然语言类比

 

    单就讲程序语言,比如啥C,C++,Java,C#之类的.所谓程序语言自然也是种语言,跟我们平常用的汉语,英语一样.并且相对我们用的自然语言而言简单很多.比如英语中有啥名词,形容词,动词,副词之类的.程序语言相应的词就是int, char,float之类的.英语中有词组短语,固定搭配.程序语言就有表达式如+,- ,+=之类的.英语有句子.那程序语言通过表达式加if,else,for之类关键词一起组合成一个兔子.然后再是一个函数,类啊就相当于是句子子组成的段落.当然这是个不太准确的类比.

   我们知道给一种语言定义一些文字符号,定义一些语法规则,一个语法就从此诞生了,程序语言你定义一些关键字,语法规则后也就是一门新语言了.比如我用weiwenhp来代替class,然后把其他关键字也替换成任何字符.这都可以的.但这时语言只是死的语言,要怎么让它活起来呢.假如以前从没有文字,你发第一个发明了文字.当然之前要会说话.于是你可以指导别人,把你发明的文字符号与现实世界中的事物一一对应起来.而现实的世界在计算机中就相当于CPU,内存等硬件资源.你得把你的语言操作与硬件一一对应起来.你要最终能让你的语言能操作硬件.

 

硬件怎么识别01串

 而硬件它只能识别01这样的数字.于是你发明的程序语言中的啥关键字,语法操作最终要用01来表示.以前我一直很纳闷,软件跟硬件到底是怎么交互的,硬件它怎么能识别数字0101啊.难道你写一串0101人家硬件就那么聪明就认识啊.实际上我们说的硬件识别0101是不准确的,硬件只识别电流,跟我们所有的电器一样,它们只识别电流,因为电是带有能量的,传到机器中把电能转化动能机器才动作起来.维持世界万物运转的是能量.那计算机硬件的话会根据电流强弱来做判断,比如假如某个晶体管的开关是连上的,那有电流,于是就当作1,而如果断开的电流可能弱到快没有了,就当成0.我可能这样说的也不准确,但大概意思是那样吧.那我们所说的把程序语言编译成0101,实际上保存在计算机中之后就是某个晶体管开关关上表示1,断开是0.至于具体又是怎么去开和关开关我就不是太清楚了啊.所以实际上我们把可执行代码,或者任意其他信息用U盘拷贝或通过网络传输过来,或者通过鼠标键盘这样的输入设备弄到电脑上的时候都对晶体管进行了操作,把信息用晶体管表示了.然后通电后,或者你做啥操作后,机器中电流不停的流来流去,然后晶体管不停的开关.这就是计算机的操作

(后面想了下可能上面这样说也不太准确(不同的存储设备原理不一样,可能也会有差别.光盘就貌似靠识别凹凸不平的点点识别01?硬盘靠有没有磁化?不太确定.不过反正有一点肯定没错,就是是使用一些看得见摸得着的物理设备的两个相反的属性来表示01,不过应该在最终被识别时还得通电,然后电流不一样才能知道吧)

我这只是不太准确的描述下,实际上背后具体实现非常复杂,很多地方我也不懂.我只是讲下大概思想.

 

编译器的作用

我们知道实际所有文字信息和图片信息在计算机中都一样,都是0101,也就是一堆堆的晶体管开或关的状态.所以你刚写好的源代码与最后编译出来的可执行文件,在计算机中的表示是完全一样的,都是0101.只不过源代码中0101的顺序和数量跟可执行文件中的不一样.在计算机中0101数量和顺序的不一样表示的信息就不一样.至于为啥对可执行文件和一般文件的操作不一样,这个可能执行时会根据一些信息做不同的处理.

实际上我们常还说汇编器,连接器之类的.反正我们不用管这些了,为了讨论的方便全部统称为编译器算了.反正就是做一个翻译的工作,把一种0101序列转换成另一个01序列.只不过这里面转换的规则和逻辑非常非常复杂.

所以发明一个程序语言,定义语法虽然也很重要,里面体现很多思想和逻辑.但要整个编译器把你写的源码翻译成另一个01序列就是极难的啊.能去开发编译器的可都是牛人啊.开发编译器自然要用到机器语言,但你想想那么多复杂的操作都用01来写?太恐怖了吧.实际上也不是,这是个迭代的过程.比如先写一点点机器语言实现一些简单的操作,然后你可以重复利用这些简单操作的组合形成更复杂的操作.而且可以利用别人的成果.比如有汇编器了,你直接用汇编语言写编译器,然后用别人写好的汇编器翻译成机器语言.人家有C,C++的编译器了,你可以直接拿来利用,你直接用C或C++来写编译器也行.

而且翻译器翻译可不能出错啊,假如你编译器很烂,没有翻译准确,那程序写的再好,再牛逼,结果在计算机上一跑也错误一堆.

 

为啥制定标准

    我们知道程序语言只是定义一些标准,是写在纸上的定义.跟法律条例一样.你去不去遵守得看你自己了.所以C,C++不同的编译器支持的操作会不一样嘛,你在微软的编译器上能编译的代码拿到别的编译器上就出错了.假如这样一些情况,而且是常见的情况,你在windows上辛辛苦苦开发了一个软件(假设不用到啥MFC之类的吧),但在windows上至少也会调用些API吧.然后要移到linux上去,假如遵守了一些规则,那些API名字在windows上和linux上一样,但只是名字一样,实际上后台操作不一样.那可能把代码移到linux上稍微改动一点点或者完全不用改也能用.这是多幸福的事啊,如果要完全再整一个那是多麻烦的事啊.当然API一样了,那还要编译器一样才行啊,但貌似微软没有整linux上的编译器给你用吧.如果其他的编译器跟微软编译器的遵守的规则不一样.那你的代码还是没法通用.比如每家编译器厂商拿C++定义的规范来,觉得有些地方看不爽,我就不那样去整.当然大部分还得遵守.不然你支持的语言就不叫C++了啊.

   所以这样乱套了可不好,还是制定一些标准的语言规范,大家写代码时就完全按标准来,不用考虑啥编译器支持的不一样.你编译器也老实的按统一标准来吧.我们写代码的人当然希望统一标准好啊,自己写代码省事多了.可人家开发编译器的厂商可不这样想,出于一些商业目的可能就不完全按标准来.你语言规范也只是一个建议,不能像法律一样去强制别人执行.

  所以Java的一次编译到处运行,是件多么诱惑人的口号啊.因为它把语言先编译成一个中间语言,与硬件和操作系统无关.然后中间语言在Java虚拟机上运行,而在windows上和linux上那个Java虚拟机肯定是不一样的.不过虚拟机怎么整了你不用管,你只管针对虚拟机编程,不针对具体的操作系统.不过据传闻在但跨平台时有时还是会碰到很多问题,这可能还是需要做修改,但肯定也不用修改非常多吧.

 

程序语言与类库的关系

程序语言定义了一些规则,你按照规则去写代码,然后编译器去给你翻译下就完事了.但你实现一个简单的操作都得写非常非常多的代码.所以很多厂商给你写好一些代码,你只管去调用下就行.这就是类库.一般是编译器厂商给你做很多免费的类库用,当然也不能说免费,因为你买了集成开发环境嘛(IDE).实际上我们平时用微软的Visual sudio,它里面包括很多东西的,有啥编译器啊,类库啊,还有些智能提示的工具啊.我们平时敲一个点点然后带出来一堆函数名啥的给你选,这都是集成开发工具干的活,跟那个程序语言本身可没半毛钱关系.

关于C++的类库有很多,比如很多GUI类库,MFC, QT,GTK.实际上它们跟C++语言本身没啥关系的,只是它们给你写了很多代码可以让你拿来调用.

另外一些类库比较庞大,各个类之间不家千丝万缕的联系.我们就叫框架,比如MFC就是一个框架.其实我们也可以简单的把一些复杂的类库看成框架就OK.

 

什么样的程序语言是好语言

所以你要想自己发明一种新的程序语言,你得自己制定语法规则,然后自己写编译器.可能制定语法规则容易,因为有那么多可参考的.但编译器可难了啊.你也别指望别人给你开发.一般一个语言刚出来不怎么受关注,等用的人多了,热门了.别人可能才会也给你整个编译器出来.

那么什么样的语言才是好语言呢.从大的方面讲就是用起来方便,容易上手,不容易出错,而且在计算机上执行时效率高,运行的快,占内存,CPU资源少.但要使一门语言简单好用编译器就得多做很多事,有时甚至得搞个像Java虚拟机和C#中CLR去给你多做很多事.比如管理内存.你就永远不用担心啥内存泄露了啊.但这些机制给你多做了很多事,肯定会导致效率和性能的降低,当然只要别低的太离谱我们是能接受的.另外针对一门语言可用的类库越多自然越好,很多功能我们调用个类库搞定就不用自己从头整起了.

 当然好的语言不一定热门,这还跟一些商业因素有关.

另外程序语言只是个工具,我们的最终目的是操作计算机硬件资源,给用户提供一些啥服务.所以某个软件好不好时人家用户可不关注你有啥语言开发的啊.他只觉得软件页面好看,用起来方便,比较流畅啊,不卡啊,一些页面看下就容易知道是提供啥功能啊.当然得到的结果可不能错啊.所以好的语言能开发出非常烂的软件,烂的语言也可能开发出好的软件.关键看用的人. 当然你如果用一个好语言开发好软件的可能性更大点了.

抱歉!评论已关闭.