C语言Ⅰ_程序运行相关

程序运行原理

从历史说起

最初的“计算机”实际上是计算器。或者说计算机实际上是为了实现自动计算而发明的。


首先为机械式计算器。

一、最初是19岁的帕斯卡在1639年发明的帕斯卡加法器。就像它的名字,帕斯卡加法器只能运算加减法。

(使用齿轮机构,拓展:https://www.jianshu.com/p/4f69217a58f8)

帕斯卡改进了水银气压计,发明了注射器、水压机。后人为了纪念他,将压强单位称为“帕斯卡”

二、1671年,著名律师莱布尼兹发明了莱布尼兹乘法器。实现了乘除法。

戈特弗里德·威廉·莱布尼茨:德国著名的思想家、哲学家、数学家、物理学家、外交家、著述家以及神学家。是数理逻辑的创始人和微积分理论的创立者。还开创了二进制。


理论的发明。

计算机之父——查尔斯·巴贝奇(Charles Babbage)于1834年发明了分析机(现代电子计算机的前身)的原理。

他曾设想根据储存数据的穿孔卡上的指令进行任何数学运算的可能性,并设想了现代计算机所具有的大多数其他特性。这些想法早于现代计算机出现200年。

他还与世界第一位程序员——阿达·洛芙莱斯(Ada Lovelace)有关。

Ada是是英国著名诗人拜伦的女儿,在17岁时于剑桥大学第一次见到了查尔斯·巴贝奇,这次相遇成了Ada人生的转折点。

之后,巴贝奇致力于发明分析机,而Ada则致力于为这台分析机编写算法,并且预言了通用计算机(可编程计算机)的可能。

她建议用二进制数,让分析机可以使用各种各样的穿孔卡:“控制卡”、“数据卡”、“操作卡”;她还提议把数字和其他符号(字母等)“编码”成数字数据,便于机器处理。


下面进入电子式计算机时代。

约翰·阿塔那索夫(John Vincent Atanasoff)在1937年将机械式计算机改成了电子式。它不可编程,仅仅设计用于求解线性方程组,并在1942年成功进行了测试。 机器使用电容器来进行数值存储,数据输入采用打孔读卡方法,还采用了二进制。


现代计算机

接下来便是电子管、晶体管、集成电路、大规模集成电路的发展流程。

在通用计算机设计中,图灵冯·诺依曼的贡献很多,也是本文说明程序运行原理的开始。

其中,图灵——计算理论,冯·诺依曼——计算机架构。


先简要说说图灵的计算理论:

​ 计算机可以看作一个数据处理器

​ 图灵模型则添加了“程序”:

输出数据依赖于程序与输入数据,注意在这里程序与输入数据是不同的元素。


下面是计算机的冯·诺依曼架构:

(与图灵模型对比一下)

它将计算机分成4个子系统:

算术逻辑单元用于数据的逻辑或算术计算,也就是数据处理的功能;

储存器用于储存数据(这里 输入数据程序 都被作为数据储存在储存器中);

控制单元用于控制其他系统进行活动。


储存器的简单结构如下:


那么程序如何执行的呢?

一个HelloWorld程序的源代码:

1
2
3
4
5
 #include <stdio.h>
int main()
{
printf("Hello World!\n");
}

经过编译器,编译成“二进制程序”,也就是计算机可以直接理解的程序,储存在硬盘中(外存)

执行程序时,计算机将编译好的程序从外存复制到主存(内存)中,再从主存复制到CPU中;然后CPU读取并执行程序,输入数据从外存或主存中复制到CPU内使用;最后将输出数据复制到输出系统(电脑屏幕)。

概括来说:

程序:外存 --> 内存 --> CPU

使用的数据:外存 --> 内存 --> CPU 或 输入系统 --> 内存 --> CPU

输出数据:CPU --> 输出系统 或 CPU --> 内存 --> 外存

源代码生成可执行文件的过程:

graph LR subgraph 编译 D["预处理(preprocessor)"] --> E["解析(parse)"] E --> F["优化(optimizer)"] end subgraph 编译执行 A["源代码(source code)"] --"编译"--> B["目标代码(object code)"] B --"连接"--> C["可执行文件(executable)"] end

内存

C语言的数据处理需要略微理解数据再内存中的结构。

数据存储在内存中,具体如下:

分成了许许多多“小房间“,每个小房间都有一个”门牌号“,一个人(数据)可以根据自己的大小(二进制长度)租用一个或多个房间。

在C语言中,数据类型(int)其实就是小房间的”租用方式“。

比如int a:如果a的内存起点是0x00000001,那么根据数据类型int,租用0x000000010x00000004四个小房间给a住;如果是其他类型,则会分配不同长度的内存以供使用。