GCC 用 C++ 来编译
openkk 12年前
<p> GCC 在 2012 年 8 月 15 日的时候,merge 了一个 patch - <a href="/misc/goto?guid=4958522457501763948" target="_blank">Merge from cxx-conversion branch</a>,这意味着,以后在 GCC 的编译只能用 C++ 的编译器了,也意味着,gcc 的实现代码开始转向 C++ 了。</p> <p> 你可能会有两个问题,</p> <ul> <li>一个问题是为什么 GCC 要转成 C++ 的实现?</li> </ul> <ul> <li>没有 C++ 的编译器,我怎么编译 C++ 编译器的代码?这不是“鸡生蛋还是蛋生鸡”的问题么?</li> </ul> <p> 那,我们来看一看吧。</p> <p> <strong>为什么要用C++</strong></p> <p> 在 <a href="/misc/goto?guid=4958522457604282385" target="_blank">GNU 的C++ Conversion 文档</a>中,我们可以在 Background 中看到这样的描述:</p> <blockquote> <p>Whether we use C or C++, we need to try to ensure that interfaces are easy to understand, that the code is reasonably modular, that the internal documentation corresponds to the code, that it is possible for new developers to write new passes and to fix bugs. Those are the important issues for us to consider. The C++ features which are not present in C – features which are well documented in many books and many web sites – are not an important issue.</p> </blockquote> <p> 这句话的意思可以理解为,今天 GCC 在用C语言的实现已经有点 hold 不住了,因为,开发人员觉得,不管我们用C或C++,都需要努力确保接口是容易理解的,这样我们的代码是想当理性地被模块化的,这样内部文档和代码一致, 这样可以更好地组织代码,这样有利于新人了 fix-bug。而 C++ 正好可以让他们更好的完成这些东西。</p> <p> GNU 还给出了下面这些理由:</p> <ul> <li>C++ 是一种标准化的,大众的,流行的语言。</li> <li>C++ 是 C90 的超集。</li> <li>C++作为C的扩展和C在性能上一样好。</li> <li>C++ 在一些有意义的案例上支持更干净的代码。</li> <li>C++ 让你更容易去写一个更干净的接口。</li> <li>C++ 永远不会让你的代码变得更丑。</li> <li>C++ 不是万灵药,他是C的一个改进。</li> </ul> <p> 然后,给了一个 PDF <a href="/misc/goto?guid=4958522457698422922">http://airs.com/ian/cxx-slides.pdf</a>,这是 Google 的<a href="/misc/goto?guid=4958522457787558241" target="_blank"> Ian Lance Taylor</a> 的的一个 PPT,这个文档可以让大家更好地理解我在《<a title="C++的坑真的多吗?" href="/misc/goto?guid=4958522457882258289" target="_blank">C++的坑多吗?</a>》一文中那些观点。<strong>我都不知道我要说多少遍 C++ 的封装,继承和多态比C语言在代码组织上要好得多得多</strong>。大家还是自己看一下代码吧:</p> <p> <strong>数据结构的操作 —— </strong>你写的一定不会有 STL 好</p> <p> <strong><a><img title="VEC vs vector" alt="GCC 用 C++ 来编译" src="https://simg.open-open.com/show/380bb74e4cdbe0ae3dc0d665013f17ea.jpg" width="542" height="343" /></a></strong></p> <p> <strong>结构套结构还是继承?</strong></p> <p style="text-align:center;"><a><img title="tree-structure" alt="GCC 用 C++ 来编译" src="https://simg.open-open.com/show/9228266b0c4f792181b1fd0ffd3afd3a.jpg" width="565" height="492" /></a></p> <p> <strong>函数指针还是多态?</strong></p> <p style="text-align:center;"><a><img title="TARGET vs Target" alt="GCC 用 C++ 来编译" src="https://simg.open-open.com/show/fb157de9aea3aa19f1e99bf7302c6217.jpg" width="489" height="587" /></a></p> <p> <strong>垃圾回收还是智能指针?</strong></p> <p style="text-align:center;"><a><img title="GC vs Smart Pointer" alt="GCC 用 C++ 来编译" src="https://simg.open-open.com/show/da3d728f3b1cb58c17fe736a0bf11f25.jpg" width="610" height="433" /></a></p> <p> <strong>Why not C++? </strong></p> <ul> <li><strong>C++慢吗</strong>?某些特性会慢,但是有时 C++ 更快,你可以只用你喜欢的 C++ 特性。</li> <li><strong>C++复杂吗?</strong>它只不过是另一种编程语言,他可以让你对程序员维护更简单。</li> <li><strong>FSF 不喜欢C++!</strong>因为 FSF(自由软件基金会)这些人不写代码。</li> </ul> <p style="text-align:center;"><a><img title="Why not C++" alt="GCC 用 C++ 来编译" src="https://simg.open-open.com/show/c9a272ab858fc2b8f72d727e4b4b9cb3.jpg" width="557" height="486" /></a></p> <p> <strong>Bootstrapping</strong></p> <p> 最后,我想来介绍一下 <a href="/misc/goto?guid=4958522457969296835" target="_blank">Bootstrapping</a>。 所谓 Bootstrapping,就是用自己这个语言写编译器来编译自己,也就是说如果你要编译 gcc,你需要用一个c的编译器来编译之,这个就是 bootstrapped process,自举过程。包括 <a title="BASIC" href="/misc/goto?guid=4958522458072531522">BASIC</a>, <a title="Algol" href="/misc/goto?guid=4958522458163170383">Algol</a>, <a title="C (programming language)" href="/misc/goto?guid=4958522458259388515">C</a>, <a title="C++" href="/misc/goto?guid=4958522458349223243">C++</a>, <a title="Pascal programming language" href="/misc/goto?guid=4958522458438312945">Pascal</a>, <a title="PL/I" href="/misc/goto?guid=4958522458537774789">PL/I</a>, <a title="Factor programming language" href="/misc/goto?guid=4958522458636829987">Factor</a>, <a title="Haskell (programming language)" href="/misc/goto?guid=4958522458721029089">Haskell</a>, <a title="Modula-2" href="/misc/goto?guid=4958522458810771760">Modula-2</a>, <a title="Oberon programming language" href="/misc/goto?guid=4958522458901515342">Oberon</a>, <a title="OCaml" href="/misc/goto?guid=4958522458999075705">OCaml</a>,<a title="Common Lisp" href="/misc/goto?guid=4958193229416944592">Common Lisp</a>, <a title="Scheme (programming language)" href="/misc/goto?guid=4958193230160972074">Scheme</a>, <a title="Java (programming language)" href="/misc/goto?guid=4958348757586126322">Java</a>, <a title="Python (programming language)" href="/misc/goto?guid=4958522459192329945">Python</a>, <a title="Scala (programming language)" href="/misc/goto?guid=4958522459279860656">Scala</a> 等语言都这么干。</p> <p> 这样干的好处主要是,自己可以测试自己,编译器的改善和语言的改善相辅相成。</p> <p> 但是,这是一个“鸡生蛋,还是蛋生鸡”的问题,如果你需要用X语言来写一个X语言编译器的语言,你可以这样干:</p> <ul> <li>用Y语言来实现X的语言解释器或编译器。 <a title="Niklaus Wirth" href="/misc/goto?guid=4958522459373634172">Niklaus Wirth</a> 说 <a title="Pascal programming language" href="/misc/goto?guid=4958522458438312945">Pascal</a> 的第一个编译器是由 <a title="Fortran" href="/misc/goto?guid=4958522459476573834">Fortran</a> 写的。</li> <li>已存在用Y语言写的X语言的编译器或解释器。<a title="Scheme (programming language)" href="/misc/goto?guid=4958193230160972074">Scheme</a> 就是这么干的。</li> <li>已经有一个编译器来编译一个早期版本的X语言,然后就可以用早期版本的X语言来编译新版本的X语言了。<a title="Java (programming language)" href="/misc/goto?guid=4958348757586126322">Java</a>,<a title="Haskell (programming language)" href="/misc/goto?guid=4958522458721029089">Haskell</a>, 和最初版的 <a title="Free Pascal" href="/misc/goto?guid=4958522459599400649">Free Pascal</a> 就是这么干的。</li> <li>X在某平台上的编译器已经存在,可以使用交叉编译技术来编译另一个平台上X语言,C语言就是这么干的。</li> <li>用X语言写一个编译器,然后手动编译之(不需要特别优化),(注:手动编译估计就是手动翻译成机器汇编代码),然后再运行这个手动编译的编译器来编译这个编译器的源码,并优化之。<a title="Donald Knuth" href="/misc/goto?guid=4958347444462088510">Donald Knuth</a> 在他的 <a title="WEB" href="/misc/goto?guid=4958522459724816496">WEB</a> <a title="Literate programming" href="/misc/goto?guid=4958522459819179651">literate programming</a> 系统里用到了这个方法。</li> </ul>