作者:PRESLAV MIHAYLOV;    翻译:Betty

原文地址:http://pmihaylov.com/category/what-you-wont-learn-in-the-basics-courses/

这篇文章是《你在基础课程中所学不到的东西》的一部分,针对那些渴望深入了解编程和计算机科学的人。

当我开始编程的时候,我接触了C #,觉得挺有趣的。随着我学习的进步,我也学习了其他的编程语言。我学习JavaScript,PHP,java。

虽然我学会了用这些语言编写代码,但我不明白的是为什么会有这么多语言呢?他们都有什么用途?此外,我很好奇这些语言是从哪里来的?他们是怎么形成的?什么是低级语言,为什么它仍然存在?

本文的目的是试图帮助你找到其中一些问题的答案,并进一步激发你对编程语言和计算机的性质的好奇心。我将带你了解现代编程语言的演变过程。他们为什么会出现,他们解决了什么问题?。

处理器及其语言

这一切都归结于计算机的中央单元——处理器。首先,让我们着眼于它的确切目的。

从根本上说,处理器是一个像热水器一样的电子装置。但热水器的电子元件组合方式的唯一目的是把里面的水加热。另一方面,处理器的一般用途就是可以用来为你的汽车创建一个设备,但是你也可以利用它在游戏机上玩你喜欢的游戏。

为了成为通用的电子设备,它必须为你提供一些可以执行的抽象指令,像加法、减法、乘法等指令。你可以用这些来计算你的薪水,但是你也可以用它们来计算你房间的温度。

因此,从根本上来说,处理器所做的就是按顺序执行指令。另一个注意事项是,现在有些处理器能够按顺序执行多个指令,但是这些功能解决了一个优化问题。他们背后的原则是相同的。

处理器与外部世界的接口是一个二进制数字的序列。为了让它执行我们所提到的抽象指令,它必须把从外部世界接受到的指令以某种方式映射成二进制数字。

机器语言

用来定义处理器支持哪些指令以及这些指令如何映射到传递给它的二进制数字的规范称为指令集架构(ISA)。现代计算机支持的指令比我展示给你的要多得多,但原理是一样的。

此外,我想提到的一点是,现代处理器在实现和功能上各不相同,但它们可能都支持一个通用的ISA。这样做的原因是,一旦我们编译了一个目标指令集的程序,这个程序就可以在多个处理器上运行。x86就是现代指令集的一个例子。

处理器所支持的二进制表示法被称为机器语言。这是计算机的核心,也是编程语言发展的基石。无论你的代码属于Java, C#, C还是Python,这些代码最终都转化为处理器的机器语言。

汇编

在计算机编程的早期,人们不得不使用字典。这本字典给他们提供信息,说明他们要执行的指令在处理器上映射成什么样的数字。将符号代码(如加、减、乘)转换成机器代码(如一组字节)的过程称为汇编。

从事这种操作的人被叫做汇编人员。如今,这种工作被汇编程序取代。它们的用途是获取用来表示CPU指令的一组符号作为输入信息、并将它们转换为机器语言。

用一系列符号来代替数字是对程序编写过程进行简化的一大进步。但是,我们仍然过于依赖基础硬件,因此,开发时间受到影响。

我将给你举一个汇编程序的例子,以便你能体会到用汇编语言来编写程序是什么样的情形。

这里是一个用高级语言编写的简单程序,它对两个数字的值进行了交换:

int temp = a;
a = b;
b = temp;

这里是用汇编语言编写的等价程序:

STORE R0, R2 // store value of register R0 to register R2
STORE R1, R0 // store value of register R1 to R0
STORE R2, R1 // store value of register R2 to R1

问题

正如你所看到的,用高级语言和汇编语言编写程序之间的最大区别在于:在第一种情况下,你处理抽象信息,如变量。在汇编程序中,你处理硬件细节,如寄存器和内存。

所有编程语言的主要目的都是为程序员提供处理抽象信息的能力。这些抽象信息对程序员来说更容易理解,而硬件细节对处理器来说更容易理解。

用汇编语言编写程序的另一个问题是你所编写的代码不可跨平台使用。如果你想编写一个必须在通用计算机和手机上都可以运行的程序,你必须用你的手机和电脑上所使用的两种不同的指令集对你的汇编代码进行重写。

现在,我不认为任何专业开发者会使用汇编语言。即使有这种情况,也可能是为了一个非常特殊的问题,而这种问题又很少遇到。然而,有些业余爱好者有可能为了好玩而使用汇编语言。

但我鼓励你在一段时间内编写汇编代码,以便更接近计算机的本质。如果你想获得这方面的知识,看看这个链接里的内容

低级语言

曾经,最早的编程语言开始出现。这些编程语言允许你编写更具有可读性的代码,因而更易于阅读和维护。这种代码经过编译转换成汇编代码,并由汇编语言进一步转换成机器语言。

C语言不是最早出现的,但也许是最著名的编程语言。编程语言的引入解决了两个主要问题:

  • 现在,程序员可以更专注于解决他们的问题,而不是处理硬件细节。当你用C语言的时候,你不必担心寄存器和内存地址。即使你有这方面的担心,至少也没有那么明显。
  • 你可以编写能够跨平台使用的代码。你可以用C语言编写一个程序,在不修改代码的情况下把它编译成不同处理器的指令集。

因此,开发时间大大缩短,程序的可移植性大大增强。但即便如此,我们仍然非常接近机器的本质。我们仍然要从指针和内存的角度思考问题。数组不是高级结构,而是实际内存的低级抽象表达。这里面还没有对象的概念。我们不是从“人、狗、猫”这样具体的角度思考问题,而是仍然从变量、结构和指针的角度进行思考。

应用

高级语言解决了使代码更简单的问题, 但这是以性能和灵活性为代价的。我们在处理资源受限的环境时仍然使用低级语言(特别是C语言)。

有一个实例是连接到你的汽车液晶显示屏或汽车里的中央计算机的小装置。

这种编程分支叫做嵌入式开发。由于低级语言的灵活性,这种开发仍然严重依赖低级语言。你不能在这样的环境中使用JavaScript。

如果你想这样做,你必须首先嵌入一个2 MB的JavaScript解释器,然后才开始编写你的程序。考虑到你车上的设备只有8 KB的内存,这可能是一个困难的挑战。

另一个依赖低级编程的有趣的领域是系统编程。这个领域的开发人员专注于开发支持其他应用程序而不是最终用户的软件系统。这种系统的一个例子是你的操作系统。

高级语言

有了高级语言,开发人员的重点就从处理硬件细节转向处理抽象信息。高级语言的目的是让开发人员专注于解决复杂的问题,而不是把注意力放在基础机械上。

这种工作重心的转变是以性能为代价。为了让开发人员免去处理指针和内存的责任,有一个垃圾收集器来进行内存管理。

此外,系统的安全性是高优先级。因此,要执行低级语言所不需要的一些检查。例如,在高级语言中,如果你试图读取越界数组的索引,则会遇到报错。在C语言中,这是未定义的行为。有时你可能会逃脱惩罚,有时系统可能会崩溃。

所有这些都会导致软件的速度变慢,使用更多的资源。但是现代硬件的能力在不断增强,在过去可能被认为耗费资源的软件,现在的费用却很低。

现代语言及其应用

Java,C#、JavaScript、Python等是高级语言。这些语言有着不同的语法和范例,但他们都是在低级语言的复杂性的基础上的重大简化。

C++是一种有趣的编程语言,它试图充分利用高级和低级语言的优势。在C++中,你可以编写低级代码,但也可以使用对象和类编写高级代码。然而,它的主要缺点是它的复杂性。它就像一把多用途瑞士军刀。对于一个只想钉钉子的程序员来说,使用这个工具是不方便的。

所有这些语言的应用范围是巨大的。你可以开发网站、移动应用程序、游戏、桌面应用程序等等。你可以用我所提到的所有语言实现所有这些应用程序。但即便如此,每一种语言都对某一特定领域有吸引力。

结论

这是对编程语言发展的一个快速浏览。每一种语言都解决不同的问题,有着各自的用途。用高级语言开发程序很容易,但低级的开发仍然有需要。这是因为我们必须在性能和易用性方面做出权衡。

但是理解不同的编程语言所解决的问题是很重要的。即使你可以用C #解决每个问题,你也应该知道它和C++相比的弱点是什么。记住,如果你拥有的只是一把锤子,一切看起来都像钉子一样。

下一次,我们将探索一个程序从源代码到可执行文件所走的路径。