<audio id="audio" title="01 | 学习编程，我到底该选择哪门语言？" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/95/fc/95e5cb2f5d269772fb71cbb78c7fdefc.mp3"></audio>

你好，我是胡光。欢迎来到我的极客时间专栏。在接下来的两个多月里，我将陪伴在你的每一天的清晨或是夜晚，在人潮拥挤的上班地铁上，在你家里的书桌前，再或者是在你公司楼下的咖啡厅里，每天10分钟，让好学的你，有所收获，就是我的任务。

## 那些年，我学过的编程语言

面对编程这个话题，或许你已是一位编程老手，对编程熟悉无比，现在是想查缺补漏；亦或许你是一个纯新手，对编程一无所知，学习完全是从0开始。不管哪种情况，在我们讨论编程学习的时候，怎么都绕不开一个话题，那就是语言选择。

鉴于以往的工作经历，我了解或者熟悉的编程语言有十几种之多，包括：

- 最能反映系统本质的 C 语言
- 叫人难以捉摸的 C++
- 天生就格式优美的 Python
- 上古级的 Pascal
- 神奇的函数式编程语言 JavaScript
- 微软系的王牌语言 C#
- 被誉为世界上最好语言的 PHP
- 使用人数最多的 Java
- 能够方便操作系统的 Shell 脚本语言
- 还有我自己开发的一门娱乐级编程语言 Hython

此外，还有一些仅仅是使用过，能看懂的语言，就不列出来了。

你可能会有疑问了，为什么我会这么多编程语言呢？原因很简单，工作中是一个边学习边工作的过程，不同编程语言擅长做的事情不一样，让专业的语言干专业的事情，这是一个程序开发人员最基本的认知，所以我能学会多种编程语言也是情理之中。

你可能又会问了，学习了这么多编程语言，难道不会造成混淆么？其实，编程语言设计者，更多的还是为了让人们使用自己的编程语言进行开发，所以语言设计本身都会有前辈语言的主流特征，这也就是为什么，只要你学习了一门主流语言后，会大大降低你学习第二门语言的成本。可第一门语言的选择，是门技术活，这也是今天我们要讲的主题。

最后你是否好奇：“**我为什么还要自己开发一门娱乐级编程语言呢？**”简单点儿回答就是：自娱自乐。正式点儿的回答就是：经历了开发编程语言这个过程，会对很多语言的特性理解得更深刻，知其然，知其所以然。所以当你自己能开发出一门编程语言的时候，站在开发者的角度再去学习其他编程语言，简直就属于“降维打击”般的学习。

## Pascal、C、Python，哪个是你的首选？

刚才列举了十多种编程语言，接下来我会以我的亲身经历，来说说学习不同语言都有什么样的体验，以及我在学习这些语言的过程中，遇到的惊喜和踩过的坑。

我从2006年开始接触编程，那年，我们微机老师向我们推介一门除数学、物理、生物和化学以外的第五大学科竞赛“信息学竞赛”。我当时对计算机的印象，还停留在《热血传奇》《半条命》和《红色警戒》那个阶段，没错，我对计算机的认识都是和游戏相关。当时老师在台上介绍了一大堆东西，现在我已经忘得一干二净了。

但有件事至今我还记得：课间的时候，我问老师：老师，编程学好了，能做游戏么？老师说了一声：恩！就是那种不置可否的“恩”，可以自行脑部相声演员岳云鹏的那个"恩"。对于幼小的我来说，这就是肯定句，从此我就踏上了学习编程的道路。

我所接触的第一门编程语言是 Pascal，这是一门上古级的编程语言，语法风格类似现在的 Python 和 C 的混搭风。现在没有多少人使用的原因，我猜是因为其特立独行的语法规则。Pascal 程序需要你在最开始把所有需要的变量都定义一个遍，然后再描述程序的过程逻辑。所以当时我们打趣说，作为 Pascal 的忠实用户，我们比那些使用 C 语言的要思虑周全。

下面放一段 Pascal 的“判断素数”的程序，你自己感受一下这门上古级语言那遮挡不住的力量。这段代码你看不懂没关系，只是让你对Pascal 有个直观的感受。

```
program JudgePrime;                // 程序名称
var x, i : integer; f : boolean;   // 变量仅能在此定义
begin
    readln(x);
    f := true;
    if x &lt; 2 then 
    begin 
        write('F'); 
        exit; 
    end;
    for i:=2 to trunc(sqrt(x)) do
        if x mod i=0 then f:=false;
    if f then write('T') else write('F');
end.

```

在这段用 Pascal 写的判断素数的程序中，第一行是程序的名字，第二行就是定义变量部分，并且变量只能在这里定义。从 begin 到 end. 中间就是我们所谓的程序逻辑部分了，是不是有种看 Python 代码的感觉？

你能想象么，那时稚嫩的我，在定义变量名这件事儿上，把26个英文字母都用遍了以后，最后不得不使用类似 “aa”“bb”“ccd” 这种变量名，往事不堪回首啊。

过了两年，为了参加 ACM 竞赛，不得不学习 C++ 了，准确地说，是学习 C 语言风格的 C++，就像印度人说英语，怎么说怎么一股咖喱味儿。因此，在转 C 语言之前，我还有点儿担心这个过程会比较坎坷，谁知道，就用了几天的时间，就搞定了我编程时候需要的几乎全部语法。你要知道，我学习 Pascal 的时候，可是花了四个月啊！

从这以后，我才意识到那句话的真正含义，那句话是这样说的：“语言从来不是编程的障碍，思维才是”。所谓“思维”大多数的时候，反映出来的是“编程技巧”，更形式化一点，我们叫它 “编程范式” 和 “算法数据结构”，这部分的东西，我后面还会着重讲解，并且会教你一些提升编程技巧方法。

当时的 C 语言，真是一上来就让我欲罢不能。下面我给你来一段判断素数的 C 语言程序，你来感受一下，就像感受一个刚从牢笼中挣脱出来的鸟，正如汪峰有首歌所唱的：这是自由的感觉！

```
#include &lt;stdio.h&gt;

int main() {
    int x;                   // 定义变量x
    scanf(&quot;%d&quot;, &amp;x);
    int f = 0;               // 定义变量 f
    for (int i = 2; i * i &lt;= x; i++) { // 定义循环变量i     
        if (x % i) continue;
        f = 1;
        break;
    }
    if (f) printf(&quot;F\n&quot;);
    else printf(&quot;T&quot;);
    return 0;
}

```

和上面的那段 Pascal 程序对比，你发现差别了么？对！就是变量定义这里，C 语言中我想在哪里定义，就在哪里定义！从此我跟 C 语言进入了蜜月期。

C 语言除了可以随处定义变量这个特性，它与Pascal 语言还有什么不同的特性呢？这里就不得不提到我曾经做数独程序的经历了。有一次我在做一个数独的题目，就是每行、每列和每个3*3的宫格内部，不重复地填上1～9这9个数字。

这个问题我曾经用 Pascal 语言做过，解题思路是：每次向函数中传入一个代表数独的数组作为参数，然后不断尝试修改这个数组中相应位置的值，如果尝试进行不下去了，就回到上一个状态，重新尝试。

我就原封不动地将 Pascal 语言的解题思路搬到了 C 语言中，但怎么调试都是错的，我自己反反复复检查逻辑，可就是查不出错误。在挣扎了一下午以后，我终于忍不住，求助了学长，这才发现，有一个关键的语言特性，C 语言和 Pascal 完全不一样。下面我就说说这个事儿，你现在听不懂没关系，希望你记住这个事情，等到我们一起学习了一段时间以后，你再回头来细看这段。

普通变量向函数中传值，就是将原变量中的值拷贝给函数参数的过程，这个过程，我们称作“实参给形参赋值”。原变量就是实参，函数参数就是形参。在这个过程中，本质上还是两个变量，两片独立的存储位置，也就意味着，我们对形参的改动，不会影响实参。这一点上，C 语言和 Pascal 是完全一致的，下面就要说到不太一样的地方了。

<img src="https://static001.geekbang.org/resource/image/33/65/33a9733f80d76da885c16b1bcb09e165.jpg" alt="">

请观察图1，在 Pascal 中，如果你将一个数组作为参数传递给一个函数，函数内部还是会复制一份这个数组，也就是说，在 Pascal 中数组的传递过程和普通变量的传递过程没有任何区别。

<img src="https://static001.geekbang.org/resource/image/e9/56/e9a796386b27d4b3eb76b65194b37356.jpg" alt="">

你再观察图2，图2展示的是 C 语言中数组作为参数传递的方式，你在图中会看到一个 “0x1234” 的信息，我们称之为地址，就类似于你家的门牌号。当我们传递一个数组时，其实在传递的是数组的首地址，也就是说，无论实参还是形参，实际上指向同一片存储区！

总结来说，对于数组，Pascal 函数内外，是两个互不相同，互不影响的存储区。C 语言则是函数内外是同一片存储区，任何一个修改，都意味着外部的数组也被修改了。就是这点差异，导致我用一下午也没找到错误的原因！

看了上面这段，不知道你可不可以理解我当时的困扰。我当时用 Pascal 的语言特性去检查 C 语言的程序，从逻辑上来讲，当然是发现不了任何 Bug 了。当时我还以为这个语言特性，是 C 的特立独行，后来才发现，特立独行的是 Pascal。

从我的这段经历你可以发现，**初学编程选择什么语言作为自己的第一门语言是多么重要**。如果你选择一个比较“偏”的语言，形成了它独特的语言特性，可能会对你学习其他语言造成不小的困扰。而C 语言，由于它的共通性，很少会出现这样的问题。

最后给你介绍的一门语言就是 Python，上面我们欣赏过了从 Pascal 过渡到 C 语言的神清气爽，那你知道如果你学完 C，再学 Python，是什么感觉么？简直就跟吃了一大口芥末一样，提神！下面来看看 Python 的判断素数的一个程序。

```
#!/usr/bin/env python
# coding=utf-8
x = int(input())
i = 2
while i * i &lt;= x:
    if x % i == 0:
        print(&quot;F&quot;)
        break
    i = i + 1
else:
    print(&quot;T&quot;)

```

对比上面的两段代码， Python 的这份代码，是不是看着就简洁、清爽？而 Python 为什么被评价为天生就格式优美呢？那是因为，在 Python 中，如果你不按照缩进组织程序的层次关系，你的程序根本没有办法正常运行。

不同的人编写代码可能有不同的风格，就像C 语言，10个人可能就有10种风格，但Python的代码风格就像人的指纹，它是天生的，不管多少人用Python编写代码，可能也只有一种风格。所以无论你是否写过程序，在写 Python 的时候，都将写得很漂亮，很舒服。

最适合学习编程的操作系统是 Linux，Linux 中有一个核心设计思想，叫做“一切皆文件”，理解了文件，就理解了整个 Linux 操作系统，这里说的文件，可不是你所认为的常规的 windows文件。Linux 世界中的文件，就像是我们这个世界中的原子一样，是一种本质。

而 Python 中也有一个类似的核心设计思想，就是“一切皆对象”，理解了什么是对象，你就理解了 Python。而这么抽象的概念，我不认为我现在可以用两三句话就给你讲明白，不过还是那个道理“语言从来不是编程的障碍”，关于对象这个概念，在你日后对编程的知识逐渐丰富起来以后，自然就会明白了。

## 编程入门，舍我其谁：C 语言

听完了以上三种语言的介绍，你可能已经打定主意准备把界面精练的 Python 作为自己学习编程的入门语言。但是如果看完下面我给你的这张图，你可能需要再考虑考虑。

<img src="https://static001.geekbang.org/resource/image/27/ad/27b55e38da2f15736e4f226a692395ad.jpg" alt="">

上图中的时间，只是一个参考，可能你比较有天赋，会比图中所标记时间用时短，可绝大多数的人，只会多于图上的时间，不会更少的。你会看到图上有两条学习路径，绿色的学习路径用时两个月多一点，红色的学习路径用时四个月。其实这张图，我就是想跟你说明，在我们学习过程中的一个重要的概念：学习路径。一个合理的学习路径，可以帮助你大大缩短整体的学习时长，毕竟你的时间才是最大的成本。

其实正如你所看到的，你用相同的时间掌握了 C 语言后，会对你学习其他语言有很大的帮助。反观，如果你一上来掌握的就是拥有很多奇怪语法特性的语言，不仅要花很长时间学，在日后的学习中，你会发现这些语法特性在其他语言甚至都找不到。基于这类知识锻炼出来的编程思维，是不具备延展性的。所以，在选择第一门语言的时候，一定要选择简洁、高效、不拘泥于语法特性的语言。就像学习武功一样，摒弃掉花拳绣腿，去稳扎稳打的进行练习，才是快速成长的诀窍。

这里，请记住：学习编程不等于学习语言，前者包含后者，也就是说想学好编程，不仅是学好语言，还有很多比语言更难的东西等着你呢。

既然要给你讲编程，我决定选择一门既可以带你潜入底层系统一窥究竟，又可以顺畅简洁表达逻辑，还没有特别多奇奇怪怪的语法特性的语言。我希望借助这门语言，让你在学习编程的过程中，能够专注于编程思维训练本身，帮助你一步一个脚印地学习编程，培养编程思维。这门语言，就是我们前文说到的 C 语言。

我有朋友是这样形容 C 语言的，我觉得很贴切，拿过来用一下，他说：学编程就像是学乾坤大挪移，而 C 就是语言中的九阳神功。

## 推荐书籍

专栏里面呢，由于篇幅有限，没有办法穷尽 C 语言的所有知识。不过，我讲的会是一些容易被你忽视的，容易被你误解的，以及你自学不容易学会的知识点。而关于 C 语言更多的知识，我专门买了市面上最畅销的 15 本C 语言的书籍，经过一番筛选之后，我选出来了以下三本小册子，推荐给你。之所以说是小册子，那是因为他们每一本较其他 C 语言的相关书籍都很薄，内容也很详实准确，并且在内容上，三本有着递进的关系。

<li>
<p>**第一本：《啊哈 C 语言》**<br>
这本由电子工业出版社出版的《啊哈 C 语言！》被叫做“厕所 C 语言教科书”。这不是在说这本书很差，恰恰相反，这是一本浅显易懂的 C 语言入门书籍，即使是利用蹲马桶的时间看上一会儿，你也是看得懂的。并且和书籍配套的还有《啊哈 C 语言！》特别版编译器，会使得你在学习 C 语言基础知识的时候，更加轻松，自在。</p>
</li>
<li>
<p>**第二本：《C 专家编程》**<br>
这本由人民邮电出版社出版的《C 专家编程》，会是你入门 C 语言以后的第二本必备书籍。这本书，会从 C 语言的发展历史讲解 C 语言中一些语法特性，以及相关语言特性当初被设计的目的，以及现有的缺陷，会给你一个更深层次的解释。并且，作者给你展现的，不仅仅是教你 C 语言语法，更多的是在给你讲 C 语言是怎么被设计出来的。这会使得你对于你今后所写的每一行代码，都会理解得比旁人深刻。</p>
</li>
<li>
<p>**第三本：《C 缺陷与陷阱》**<br>
这本也是由人民邮电出版社出版，可以说是《C 专家编程》的延续，针对性会更强，直接指出 C 语言中各种各样的问题，并且加以分析。正所谓人无完人，那么由人所设计出来的语言，当然也没有完美的。你作为外行的时候， C 语言的美足够好好体会和欣赏，可想成为内行，你就必须要知道你所使用的工具，有什么缺点和短板，这样才能真正的在日后应用中，游刃有余。</p>
</li>

## 课程小结

说了这么多，今天我只是想让你记住一件事情，不同的学习路径，会有不同的时间成本。C 语言只是我们入门编程的一个载体，也是最有效、最深刻的一个载体。从 C 语言入手，会使得你的总时间成本最低。永远记住，扎扎实实，稳扎稳打，才是真正的捷径。

最后呢，请你想一想，在你的学习过程中，有没有哪块知识，是你身边的行业前辈们告诉你很重要的，你一开始忽视了，然后过了好久，才发现，前辈说的对的，欢迎留言给我。

我是胡光，今天我们就先聊到这儿，下期内容，我们不见不散。

> 
我录制了一个关于编程环境说明的视频，如果有对编程一点也不熟悉的朋友，可以看看这个视频，了解一下编程环境。


<video poster="https://static001.geekbang.org/resource/image/6e/97/6ea2225ab478dd8cf93a6579edda7497.jpg" preload="none" controls=""><source src="https://media001.geekbang.org/customerTrans/8ea7d4d8f077bad948e0480848916f24/5c4ac391-16f6578f338-0000-0000-01d-dbacd.mp4" type="video/mp4"><source src="https://media001.geekbang.org/cdf2e7a71d7b4dbabae8a63438ea1abc/2726b8360ed745218f57c9cbee678e86-624b0e8d2150fbfc3a7c975d0a024ed4-sd.m3u8" type="application/x-mpegURL"><source src="https://media001.geekbang.org/cdf2e7a71d7b4dbabae8a63438ea1abc/2726b8360ed745218f57c9cbee678e86-ade943b9d78465c2ce45459c2e8101d6-hd.m3u8" type="application/x-mpegURL"></video>
