自学编程,从此开始

上第2学堂,听有趣的编程课

课文: 《冯·诺依曼结构》 (点击查看完整内容:视频+评测+讨论+……)

作者:第2学堂

懂冯诺依曼结构,懂计算机。

课文题图

 

第3节 冯·诺依曼结构

一部《红楼梦》,据说经学家看见“易”,道学家看见“淫”,才子看见“缠绵”,革命者看见“排满”,流言家看见宫闱秘事……我在读三年级时翻开《红楼梦》,看到是一堆的繁体字。如果现在我以程序员的眼光去“重逛”大观园,会看到什么样的红楼呢?我不知道,还是来说一说计算机的事吧。

1 什么是计算机?

有学员说:“上网的,上QQ的!玩游戏的!”。不能说完全不对,但这是以计算机的普通用户的眼光,我们现在是程序员——虽然还没有写过一行代码,但我们必须培养这方面的思维呀。

计算机,尤其是指PC(个人计算机),如果是台式机的话,通常有个显示器,还有个主机箱;如果是笔记本或平板的话,那就薄了点……还是不对,这是在从外观上描述什么叫计算机。

计算机,人类最新发明的一个伟大的工具,如今已经无处不在,并有处处地,深刻地影响着人类的生活。在漫漫的历史长河中,唯有“火、机械、电、电子”等等工具可以和计算机比肩……这一段好有深度,但怎么听怎么像是历史学家在说话。

1.1 “冯诺依曼”版

不能浪费大家的时间了,让我们先搬出一位名人来。计算机界的名人。第一位搬出的,是有“计算机之父”之称的“约翰·冯·诺依曼”。祖师爷提出了两个现代计算机最为关键的理论:一是数字计算机的数制采用二进制;二是计算机应该按照程序顺序执行。人们称之为“冯·诺依曼体系结构”。

img

图 1-1冯•诺依曼 (John von Neumann,1903-1957)图片来自互联网

冯·诺依曼明确提出此类计算机采用二进制数制,以充分发挥电子器件的工作特点,简化了机器的逻辑线路设计,如果这个只能算是一种思路话,那么冯同学把“程序”和“程序所处理的数据”都看成计算机的输入数据,并且可以保存到计算机内部,需要时可再次加载这样的想法,就是一种思想了。

计算机原本只用于科研(包括服务战争),但现在早就 “旧时王谢堂前燕,飞入寻常百姓家”,全世界千家万户在使用的计算机,都采用冯·诺依曼当初所提出的架构。

符合“冯·诺依曼体系结构”的计算机,都需要拥有以下五大部件:运算器CA、逻辑控制器CC、存储器M、输入装置I和输出装置O。其中“存储器M”的存在尤为出彩。

1.2 “白话 C++”版

结合名家的理论,我们用自己的话,想想什么是计算机。

首先,计算机由硬件和软件组成。至于什么叫硬件(什么叫软件,我们下一小节说明)。

接着,计算机硬件的组成,冯先知说了,有五个部分:“运算器CA、逻辑控制器CC、存储器M、输入装置I和输出装置O”。我们可以进一步归纳成三部分:

  1. 中央处理器(运算器+控制器)
  2. 存储设备(内存+外存)
  3. 输入/输出设备

学习未知的东西,最好是从已知的知识中获得启发,我们以汽车做比喻,它有什么中央处理器、存储设备和输入输出呢?

汽车的组成
输入设备 方向盘、油门、刹车板……
输出设备 车轮……
处理器 齿轮、轴承……
存储设备 油箱、水箱……

表格 1-1 汽车的输入、输出、存储设备及“中央处理器 ”

1.2.1 汽车的“输入输出设备”

通过方向盘的输入,可输出车轮的转向……

通过油门或刹车板,可以输出车轮的转速……

不要混淆“输入输出设备”和“输入输出数据”。方向盘是设备,而你转方向盘时的动作中包含的力量扭矩、速度、力度,那些是输入数据。

车轮是输出设备,输出数据是车的速度,车的行驶方向。

1.2.2 汽车的“中央处理器”

汽车处理器是引擎。有人说应该是驾驶员的大脑,这似是而非,人不是汽车的一部分,人是汽车的用户,同理,你使用计算机,但你不是计算机的中央处理器。

处理器的典型工作是“吃”进一些数据,然后“吐”出一些数据。吃与吐之间,存在某种既定逻辑的处理,从而体现到数据在输入前和输出后将发生某种可预测的变化,这些变化就是处理的成果。我们的胃就是一台强大的处理器——当你还不是程序员时,你应该没有这么思考过你的五脏六腑。

“处理器”的定义明白了,那又为什么要加一个“中央”来修饰呢?一台设备往往有多个处理器,但如果其中一个连接设备的主要或多数输入输出设备时,被称作“中央处理器”。人的中央处理器应该是大脑,它通过神经连接、控制人体。

基于上述解释,对汽车而言,直接或间接接受“方向盘,刹车板、油门”等这些输入、并将动力输出“车轮”的引擎和外部各类连杆,可称为它的中央处理器。当你踩下油门,同时把方向盘打向左,那些齿轮、轴承等设备,忠实而精确进行了运算,于是车轮向左一拐,并加速飞驰——在路的右边,是万丈悬崖。处理器必须竭尽全力提供精确可控的计算,你理解吗?

1.2.3 汽车的“存储设备”

计算机的存储设备分为“内存”和“外存”。油箱、水箱、蓄电瓶之类的设备,存储某种材料,必要时供引擎直接或间接使用。类似引擎对油、水、电根据需要每次取一些,并集中在汽缸内混合处理。比如:引擎不会蠢到直接在油箱中加电,所以汽缸可以当成是“内存”。

内存当然也很重要,智能手机内存不够大,《愤怒的小鸟》就会玩起来很卡,汽车的内存不够大,你的车就跑得不猛。

我们将更多的计算机原理级别的内容,放在后面第4章中。这一小节的内容仅讲到这里,也许你对“什么计算机”还有些模糊,不过我相信你对于我们满大街跑的汽车,一定有了新的认识。没错,当你习惯用“程序员”的眼光去这个世界,你一定会惊奇的发现:原来世间到处是输入、输出设备,到处都是处理器,到处是存储设备。站起来走走,重新鉴赏一遍家里的各类电器,或者干脆就是马桶……看出点什么了吗?

不过,如果到处是带有“处理器、输入输出、存储”的设备,那计算机的特点又是什么呢?我们将在后面的课程中回答这个涉及计算机尊严的问题。

2 代码中的“冯诺依曼“结构

视频中重点讲了: cout << "Hello world" << endl; 中的每一部分,结合冯诺依曼结构,计算机在这行代码背后干的事,可以归结为一句话——

处理器将位于内存中的 "Hello world" 和 endl 这两个数据有序地输出到屏幕。

cout 读作“c-out/西奥特”,名字中的“out”好理解,表示“输出”。“c”我的理解应是“字符/char”。

我们将“Hello world”这句话直接写在代码里,而代码被编译成程序,而程序执行时必须被载入内存,因此“Hello world ”作程序的一部分也随之进入内存。这时候,作为C/C++这样偏底层的语言的学习者,就必须有“打破砂锅问(纹)到底”的精神,非要问一句,当程序运行时,“Hello wolrd”这块数据,在内存中的哪个位置呢?

注意,如果学习的更为上层,比如Java、Python等语言,我们的建议是“别瞎问底层的事,多关心关心上层的逻辑。”。为什么?表面原因这些语言也基本无法直接访问内存,无法“窥视”数据的地址。真实原因是知识的相关性原则:C和C++都是可以直接操作计算机底层资源的的语言,这是它们的优势:比如可以因此获得更高的运行性能。既然如此,我们就必须早早地表现出“流氓”的一面: 亲,我想看到裸体,因为那才是最真实的你。我们这么辛苦学习C++这样一门号称天下第一难的语言,决不是为了看这滤镜下的程序世界,浓汝下的程序世界。

“Hello world” 是一个字符串,在C/C++语言中,它本身就是直接使用一个内存地址来表达。因此按说:

cout << "Hello world";

在屏幕上,就应该输出一个内存地址(一个整数)。但因为这块内存中存储的是字符串(你可以理解为一句话),而人类对“一句话”的最常见的需要是看到语的内容,而不是话的地址……所以,C++语言的库,在此处做了特殊处理,直接将地址中的字符串的内容输出了。如果这段话你感觉不太理解,那就将“字符串”换成“美女”。美女原本给出的是一个身份证号(内存地址),可是C++的库的设计者说,看一大串数字有嘛意思? 大家允许我直接通过这个身份号到户籍系统中将这位美女身份证上的照片(内容)输出给你们看好吗?

怎么办美女的身份证号还原回来?身份证号,哦不,是内存地址通常是一个很大的整数,在64位的环境下,可以使用一个很长很长的整数来表达,很长很长? 就是 long long 啦……实际上做的事将一个指针(内存地址)强制转换成长整数。当 cout (被欺骗后)看到 输出到自己身上的不过是一个普通的整数,(而不是字符串的地址),就进入贤者模式,淡然而无趣地输出了它。

还是前一节课介绍的那个在线编辑及编译网站,当然,我们也很希望你有空能用用上一节课介绍的更多其它类似网站。这次最终输入的代码是:

//例程2: 查看字符串数据在内存中的地址:
//作者: 丁小明 (第2学堂明星学员)

#include <iostream>

using namespace std;

int main()
{
    cout << (long long)"王语嫣" << endl;
    cout << (long long)"任盈盈" << endl;
}

圆括号 ()和分号(;)一样,非常容易一不小心就输入成中文的符号,并且不是很容易肉眼区别,要小心。