×

Loading...

再说C++ - 程序设计的进化论

本文发表在 rolia.net 枫下论坛哥在之前那篇里说过,编程语言之间没有什么优劣。只是材料、工艺、硬件技术在不停的进步,管理、商业运作和融资的方式在不停的改变,一切day-to-day life的发展都多多少少在影响着人们对电子产品的需求,从而推动着整体程序设计观念的变化。

在这个朝秦暮楚水性杨花的编程语言世界里,每一种新语言的设计,无非是为了解决一些现有的编程语言,在面对新的需求时,显得力不从心的地方。所以过去的几十年里,有许多语言产生和湮灭。未来的几十年里,同会有新的语言涌现,或旧的语言消失。


早期的程序是machine code,程序员都像电影Matrix里那样看着二进制,想象着蒙娜丽莎流口水。从1971年的10um process 到今天的 32 nm node,CPU总是要从内存里load binary instructions,对二进制的machine code解码,然后完成相应的加减乘除、move、shift等指令操作的。

汇编的产生是很自然的事。用一个字符串处理程序(assembler),把JMP (60A4)转换成C3 60 A4三个byte的machine code,执行时CPU看到C3,解码为jump,继续load下面两个byte,把60A4放在program counter里,下一个指令从60A4地址上load。

于是不用看binary了,MOV,JNZ,ADD等等比编码了的数字make sense多了。不过写汇编要求对硬件的特性,还有指令集,很了解。早期的CPU大都是CISC的,指令也繁复的一塌糊涂。所以这东西是个geek的事。

终于高级语言和Compiler/Interpreter华丽丽的出现了。人们用compiler作自动翻译,把底层的繁复知识隐藏起来。”Hello, world”变成小学生也很快就能学会的东东,计算机可以从娃娃抓起了。

其实你可以看出,广大Programmer最大的优点是懒 – 就是因为懒,为了少写几行程序,才发明了一个又一个编程语言。

C是一种Compiled Language。Compiler把Source Code直接转变为Machine Code,在运行的时候CPU看到的是Instructions。所以Compiled Language在运行时很高效。在Embedded世界里,各种千差万别的系统架构都要由高效的Compiled Language来写 – 用此来压低对CPU/内存/总线的要求,而且降低能耗,to reduce hardware cost,更加便携,and better battery life, etc.

Java/C#等号称JIT Compile,但是也属于Interpreted Language。毕竟,同一个++i,Compiled Language一般只要1-3个CPU cycle(s) – this differs depends on RISC/CISC CPU。JVM执行起来,则要耗10+ CPU cycles。所以virtual machine这东西是90后也不奇怪 – 在CPU比较慢的年代,咱都耽误不起那功夫。

别看”Hello World”程序那么简单,C语言的Programmer应该有深厚的CPU和硬件知识,对Compiler有相当的了解,以及对OS的内存管理、Task调度的知识,才能写出有质量的程序。不过这么NB的Programmer一般都没什么时间写程序。

说到这里提一下C++。好多人认为C++和C是两种不同的语言,哥对此不以为然。

要知道C++语言设计的基本原则之一就是和C兼容。哥写C程序的时候,脑子里想的是编译之后的汇编指令是如何在CPU里执行的。写C++的时候,想的还是汇编。

C++的出现,是因为当C进化了10年之后,程序越写越庞大,越写越复杂,程序在Architecture Design上出现了瓶颈。其实在C++之前,许多C程序里就出现了通过Function Pointer + Callback的方式来实现OO设计。C++本身,是通过compiler来实现OO。而不是一些fancy的C语言的编程手法。

顺便说一下隔壁楼的贴,说没见过好的C++国人,要人帖个C++程序给哥看。哥觉得每个人的境遇不同哈,没见过不代表没有。哥周围就好几个C++超人。还有C++是个Architecture Design进步,程序没有到几十万行,开发团队在10个人以内,看不大出不同的架构设计之间的差别。打个比方,难道咱换个马桶,还要请architect设计吗?所以贴个程序给哥看应该是开玩笑了。

要说决大多数C++ Programmer,都只为了养家糊口而以,大多是一知半解的。所以后来遍地都是漏洞,错误百出的C++程序,一点也不奇怪。GP CPU的速度和存储器的容量进步神速。Java/C#等基于Virtual Machine的语言于是应运而生,把底层硬件,还有OS,与程序隔离开。于是Programmer的门槛降低了很多。不用有Paging, Stack, Kernel, Assembly, CPU, Cache, Bus, RAM, Interrupt, IO的概念,就可以写程序。顶多是把Virtual Machine或者Script Engine写死,只要OS稳定,别的Task就不受影响。

总结一下。哥希望各位聪明人看出来了语言背后,是硬件工艺的进步和商业运作的推动。C/C++通过提高运行的效率来降低硬件的Cost,但是对Programmer的要求比较高 (thus higher pay)。Sun和MS主推的Java/C#对Programmer的要求低一些(thus less labor cost),但是对硬件的要求就高了。

各种程序设计语言,都是Programmer们面对当前bottle neck时,生琢磨出来的。语言将来如何进化,要看今天的程序设计面对哪些问题。不过当前各种语言的Compiler也好,Virtual Machine也好,Script Engine也好,几乎清一色是C++写的。如果你是个Rookie,C++是很值得花心思学好的。Regardless how programming languages are going to evolve,你都能在C++ 里找到设计者的思想。更多精彩文章及讨论,请光临枫下论坛 rolia.net
Sign in and Reply
Modify
Report

Replies, comments and Discussions:

  • 工作学习 / 科技领域杂谈 / 再说C++ - 程序设计的进化论
    • 楼主对 c++ 一厢情愿
      楼主对 java/c# 的了解欠完整 , JIT compilier 在把 byte code 编译成 machine code 的时候是非常高效的, 比如加法运算, 不会比 c/c++ 慢. 甚至在某些情况会更快. 大多数情况下, 编译 c/c++ 的时候很难对处理器做优化, 所以生成的 machine 都是 x86, 而 jit 可以针对 cpu 生成最优代码.

      此外, c++ 并没有你想象的高效, 很多研究表明 c++ 的性能优势比 java 不足 100%. 而优化滴 c 可以达到 java 的 2-3 倍
    • "但是对Programmer的要求比较高 (thus higher pay)"?pay的高低是由supply & demand决定的。
    • You know your stuff, you are good at it, and you can write. PFPF, indeed! But, it can't be more wrong "写C++的时候,想的还是汇编".
      高级语义由其存在的道理,分层设计才能scale. portability的重要意义就是在各种平台上全能跑。RISC, CISC, (or MISC, I meant Macro ISC, I was part of the original design group), 汇编怎能一样? 就算是一种机器,想想10年之后,万一咱编的source code还活着,那时候的机器结构也许和现今完全不同,为今天某种机器编译优化而考虑设计的源码,和为解决某个商业用途而设计的源码,哪个生命力更强? Of course, it is a different story if you are writing code for system or embedded.

      Bjarne Stroustrup said "code for the use of others is key".
      • 老猫说的很有道理。按说C++追求的是Architecture,应该独立于硬件才对 - 还引用了哥的偶像的话……
        And yes, it IS a different world in system architecture.

        "code for the use of others is the key"这话没错,但是in C++,即使是架构设计,也该考虑不同CPU的特性。每个系统/应用都是基于某个硬件平台写的。C++封装的时候,要考虑跨平台,也要考虑各个平台具体的特性。举个例子吧,某个OS里的程序 -

        #ifdef _RISC_CPU_
        #define CCpuDriverClass CRiscCpuDriverClass
        #elif _CISC_CPU_
        #define CCpuDriverClass CCiscCpuDriverClass
        #endif

        CCpuDriverClass cpu_driver_instance;

        话说回来,哥也觉得任何与硬件无关的application开发都该用intepreted language。C++本来就是一种System Programming Language。

        10年后的计算机,也许CPU用光不用电了。真希望这一天早点到来。
    • "写C++的时候,想的还是汇编" --- 听着别扭. 写C++的时候, 想的是Architecture Design.
    • 分析得很全面. 让我想起一哥们对手动波解释.手动波虽老款难用对司机的要求高,但让人有人车一体的感觉-找到设计者的思想,再说自动波是从手动波进化来的,大车(赛车?)还免不了用手动波.
    • 补充一点:Code labour 和 software engineer 还是有很大区别的
      加拿大最好和最坏的地方,就是有很多培训学校,像青山学院 维多利亚什么的,
      结果很多学英语的学文学的经过半年培训竟然比计算机科班出身更容易找到工作,人家英语好啊。
      然后他们就很自豪地说,原来你们软件行业这么简单啊,我半年就成了软件工程师了。

      其实他们只能算个code labour,和工厂流水线上的工人性质是一样的。

      真正的软件工程师 目的不是编软件,是用软件来完成一件工程,软件只是一个辅助工具。
      只不过很多人来到加国,因为语言的问题,很多在国内做系统设计的也只能沦落到写代码了。
      龙游浅滩和水牛为伍了。
      其实锥未放到囊中,一旦遇到才能脱颖而出了。
    • 上面是讲到了一个方面。可笑的是那些什么WHILETRUE还能说事的人。有的时候时间就是钱。写个股票下单的,10毫秒级别的,能讲什么OO?这样的人一小时180块。那些能讲话的人估计就是在大银行里写写是个人就能写的ABC.
      • 你单位写得没错,是毫秒?那就太慢了,如果要有竞争力,还需努力.
        • 嗯,我就是个纳秒级别的,战斗力30000。
        • 那是一个CPU TICK的大小。当然也难怪你, 懂JAVA的基本上也不知道什么是CPU TICK
          • 10个毫秒, 那是一个CPU TICK的大小, 哦,..........
          • 好大的CPU...
            • 二位是典型地卖弄自己的无知的人物。
              • 您是写股票下单的?
              • 嘿嘿,我“卖弄”的可都是你自己的原话。要不科普下什么是CPU tick吧。让我们做java的也明白一下。
        • 管他什么C/C++,汇编,我需要的就是写纳秒级别的程序员。我是做股票自动交易下单的。我在Nasdaq 数据中心有2个机柜,有所有的数据 , 网络, 机器。本人也是程序员,愿意一起在这个方向发展的人给我联系。
          做一个能挣钱的交易系统不容易,也不难,关键是需要一些的条件。 有意 PM.
          • 单子只在NASDAQ交易吗?
            • 在NYSE/BATS 也有一个机柜,NASDAQ->NYSE 光纤相连,到EDGX/EDGA也是光纤。
              • 时间要求这样高,你是搞 arbitrage 的?
              • Are you working for Swifttrade or some day trading company?
          • 说来听听你们的系统是什么样的?micro seconds 已经很好了.
          • 感兴趣. 我在交易所也只在微秒级别挣扎. 你这个是啥系统? 硬件吗? 算法交易不是挺复杂的吗?
            • 抱歉,我的系统也是微秒级别,不是纳秒。我希望能有人帮我进步到纳秒。呵呵
      • while(TRUE) 怎么啦?该用的时候还是得用。
        本文发表在 rolia.net 枫下论坛用C,C++还是JAVA跟写程序的水平有什么关系,不都是看具体应用吗?谁倒是在8086上用Java写个实时应用系统玩玩?

        举个例子,具体到某个作家,用电脑写的小说就比用钢笔写的好?在太空舱里写日记该用铅笔还是圆珠笔?

        那谁说火星探测器都用Java写的?要说探测器上的某个应用软件(比如都收集到的数据进行处理)用Java写还有点谱,可打死我也不信它的飞行控制都是Java写的。

        坛里有在波音、空客或者帮巴蒂工作的吗?能不能透露一下飞机的自动驾驶系统是用什么写的?汇编、C、C++、Java?还是别的什么?反正我们公司的地铁控制系统是C写的,地铁的驾驶系统是3年前才从汇编移植到C的。为什么不用C++?因为没办法(或者说没足够的时间和经费)去证明某个特定的C++编译器是安全的。要是用Java,不光要验证编译器,还有虚拟机,跑虚拟机的操作系统都需要验证。

        还有,程序写的好,设计不行也是白搭。我们组有个哥们,在日本干了十几年(没好意思问他到底干什么的),为了实现某个需求,明明以事件驱动方式50行代码就可以完成的东西,非要以轮询方式做,改了10多个文件,往现有的数据结构里增加一大堆变量,写了插入、更新、删除等好几个function去维护这些变量。

        上回看到有人嘲笑下面的代码:
        flag = func1();

        if(TRUE == flag)
        {
        return TRUE;
        }
        else
        {
        return FALSE;
        }
        我就觉得这段程序很好。比如说这个系统中规定TRUE就是整数1,FALSE就是0,万一func1犯了错误,返回一个非1非0的值,这段程序就避免了func1里面的错误继续扩散到别的function的可能。

        while(TRUE)怎么啦?有的操作系统的核心就是一个这样的循环再加若干中断处理。

        讨论编程语言的优劣实在是很无聊的事,只有最贴近具体应用的语言才是最好的语言。更多精彩文章及讨论,请光临枫下论坛 rolia.net
        • 嗨,您就这水平,还在这嚷嚷。让俺帮你改改你的code. 您的9行code,有8行是浪费。89%的浪费!!!
          return TRUE==func1();
          • 霍霍。你连我的贴都没看明白,又嚷嚷什么?
            第一,我说那9行code是我写的吗?
            第二,TRUE==func1()的值是什么?考虑过不同编译器的不同行为了吗?如果有一天,有人改了boolean型的定义,
            typdef enum {
            TRUE = 0xAA,
            FALSE= 0x55
            } boolean;
            你的code还工作吗?

            因为您水平高,所以您意想不到我们这些低水平的人会有这种奇怪的定义,是吗?
            • 呵呵,真的服了国人写C++的水平。如果您在我的选区,俺非要选您当国会议员不可,因为您不愧是创造就业机会的高手。今天您可以写下列code
              typdef enum {
              TRUE = 0xAA,
              FALSE= 0x55
              } boolean;

              明天您可以写

              string CAN = "USA";
              string USA = "CANADA";
              string CHN = "Russia";

              放心,compiler will let you pass. 而且,那些C++的累勃工将会感谢您给他们创造的工作机会。
          • .
            int foo1(int in)
            {

            if(in)
            return 1;
            else
            return 0;

            }


            int foo2(int in)
            {
            return in == 1;
            }


            after compiling:
            080483b4 <foo1>:
            80483b4: 55 push %ebp
            80483b5: 89 e5 mov %esp,%ebp
            80483b7: 83 7d 08 00 cmpl $0x0,0x8(%ebp)
            80483bb: 0f 95 c0 setne %al
            80483be: 0f b6 c0 movzbl %al,%eax
            80483c1: 5d pop %ebp
            80483c2: c3 ret

            080483c3 <foo2>:
            80483c3: 55 push %ebp
            80483c4: 89 e5 mov %esp,%ebp
            80483c6: 83 7d 08 01 cmpl $0x1,0x8(%ebp)
            80483ca: 0f 94 c0 sete %al
            80483cd: 0f b6 c0 movzbl %al,%eax
            80483d0: 5d pop %ebp
            80483d1: c3 ret
        • 一个这样的循环再加若干中断处理那叫调度系统,一定要叫操作系统也拦不住您。
          • 如果你非认为几大管理都齐全的才叫操作系统我也拦不住你。
        • 如果func1()返回一个非1非0的值,这段程序返回FALSE,您觉得这个比返回TRUE更对?这段代码不光要被嘲笑,而且作者应该送进精神病院。再说了,即使要这样写,难道 return (TRUE==func1())? TRUE : FALSE; 岂不更好?
          • 你说的对,不过具体情况具体分析。当外部程序(系统)出错的时候,有的时候我们希望Halt掉整个系统,比如一个我信任的一个子系统;有的时候我只会给出一个错误信息,并选择一个相对安全的执行分支,比如用户输入错误;有的时候可以完全忽略,比如临时的通讯故障。
            回到上面的例子:
            “这段程序返回FALSE,您觉得这个比返回TRUE更对?”
            要看返回FALSE和返回TRUE的目的是什么。如果返回FALSE会给飞机指令“继续盘旋”,而返回TRUE则会给指令“强行降落”,我觉得“返回FALSE比返回TRUE更对"!

            另外,我没有说那9行的程序是最好的。我的意思是:在某些特定应用下的程序看上去是可笑的,但它不见得是不对的。当我们不分青红皂白地任意批判的时候,有没有感觉到自己的浅薄呢?
    • C++的缺点效率低,面向对象增加堆栈负担,是很吃内存的。所以过程式语言如C依然活着挺好,Linux的内核绝大部分还是用C写的。随着iPhone和iPAD的推出,目前C++的兄弟Object C比C++还热。为何Apple选择Object C而不是C++?
      • 因为C++被微软塞入大量私货,不兼容了。
        • Example?
      • Apple chooses Objective-C simply because Mac OS X was based from NeXTSTEP. And why C++ uses more stack than C?
    • local = (char *(*)()) inc_1;