这一章依旧会唠叨很多,才会涉及到代码
首先得知道编程是什么
为了减少篇幅,我尽量说的简单
计算机主要有两个作用,一是存储,而是计算,科学家们最早也是因为这两个原因而发展出计算机原理,而发明计算机的。
计算机和人类交互是通过其输入输出设备,正如人类和人类交互,也是通过说话和听话。我们将计算机抽象的看成是通过CPU进行读取输入,进行计算,进行输出的机器。而这里的输入和输出的地方暂时看成内存。计算则是一些基础的计算和用他们组合进行的计算。
计算机进行基础计算的原理是通过对二进制数进行逻辑运算转换成某种基础计算机的结果,复杂计算则是将基础运算混合起来实现的。
计算机在执行计算前必须先知道它到底要计算什么,因此需要外部设备给其提供指令,计算机进行执行。计算机的主要指令除了知道要怎么计算以外,还要知道需要计算什么。这个就得靠输入了,计算机会从内存里读取数据,这个数据的位置会在之前的指令中告知。读取完成之后,计算机会将数据进行运算,将结果输出到内存中。当然,指令不只是可以让计算机计算,还可以让计算机继续执行存储在内存中的一个指令。
因为本文不涉及计算机底层原理,所以不详细讲述,感兴趣可以阅读数字电子技术和计算机组成原理相关书籍。
借此,如果想要让计算机执行相关的计算并得到结果,我们就要:给其提供指令,给其提供输入,接收其输出,这便是编程所做的事情。
编程的目的是让我们能够通过相应的输入,得到需要的输出。
由于计算机中的数据都是通过二进制表示和计算的,所以编程需要提供一些特定的二进制数据,指令因为要储存在内存中,也需要是二进制的数据。所以最早期的编程是通过输入很多的二进制代码来进行的,这样不仅可读性差,复杂,而且容易出错。
于是科学家想到了,可以把指令写成助记词,这样进行编程后,再转换成二进制的数据,于是就有了汇编语言。不同的CPU因为设计原理不同和实现的功能不同,其汇编指令也不一样,但是为了保证兼容,不同的CPU会遵守一个通用的指令规范,成为指令集,也就是架构。网上有时能看到有人讨论x86架构和arm架构,它们是目前最常用的指令集。
实际上因为生产CPU的公司,CPU的设计方式,CPU的适用范围等一系列原因,产生了数不清的架构,不同架构的汇编是不能够通用的,那怎么办?
正在开发Unix操作系统的丹尼斯也思考了这个问题,于是他想到可以用一门脱离架构的通用编程语言进行开发,然后将其翻译成汇编,最终翻译成二进制,这样只需要写一个翻译软件,就能让同一份代码在不同的设备运行。这个语言便是C语言,丹尼斯开发了它,这也是为什么Unix和类Unix都和C语言高度绑定。
C语言不仅跨平台,而且是一个简洁的高级语言,在C语言之前其实已经有很多的高级语言了(大多都是进行数学运算而生的),但是C的出现依旧是很震撼的,它不是专门用于数学运算和算法的,而是真正用于计算机。
在Unix上拥有全套的C语言开发工具,我们一一介绍。
首先,最重要的便是将C语言代码翻译成二进制的软件,它叫做编译器(compiler),在Unix上使用cc指令(C Compiler)进行调用。类Unix上使用cc的开源实现:gcc。当然,C语言现在只是一个标准,任何人都可以实现C语言的编译器,接下来的教程也将使用一个热门编译器:clang,而非gcc(没事,参数差不多)。
还需要一个编写C语言代码的工具,在Unix上可以使用Vi编辑器进行编写。Vi的开源实现有著名的Vim,Neovim等,我推荐大家用helix,它也是一个开源的Vi编辑器,操作和Vi大差不差,但是打包了很多开箱即用的功能。
如果你写了很多代码文件,那么通过cc指令同时对其编译就会很困难,而且会很慢(在以前的计算机上会很明显),cc可以把不同源文件编译成二进制的中间文件,然后再将他们合并成最终的二进制文件,此时就需要一个工具来指挥编译。
在Unix上这个工具是make,它根据开发者写的称作makefile的文件,将不同的源文件通过指定的线程数量(同时进行的任务的数量)同时编译,最终合成一个二进制文件。在类Unix系统上,这个工具有个开源替代: GNU make,用法和Unix上的一样。
这三个是最基础最主要的,接下来有些次要,不是Unix上的,但是也很重要的东西:
首先就是写代码时,可以将一些功能封装成叫做函数的东西,可以在代码中调用函数,如果所有的函数调用都完全自己写,麻烦不说,很有可能写错,所以我们需要对其的自动提示和补全,提供这一功能的是语言服务器(lsp),C语言的语言服务器不止一个,我们安装最主流的clangd即可,helix会自动使用它。
代码写多了不可能没有bug,它可能是一时疏忽大意,也可能是因为某些特殊原因,无论如何想要修复就要改代码,想改就要知道哪里的代码有问题,所以就需要在运行的时候一个一个代码的运行,这就需要调试器出马了。主流的调试器有gdb,lldb等,他们分别属于gcc和clang套件。
代码进行多次更改的时候不一定改的都是对的,每次更改需要添加说明内容,告知更改的地方,如果改错了还需要将以前的代码恢复,重新修改,在多人合作写代码的情况下,不同的人完成不同的部分,还需要将他们合并成一个项目。这些麻烦事可以通过一个叫做git的软件完成。这个软件是Linux之父Linus写的代码管理器。
于是我们需要在termux安装它们
apt install clang helix make git
凑齐这一套开发工具了。
现在进行helloworld吧。
Vim的操作各位请自行网上查找,这里不细讲。
输入
hx first.c
创建并进入first.c文件
输入以下代码:
#include <stdio.h>
int main(){
printf("hello,world!");
return 0;
}
不要惊慌,我们挨个解释:
第一行include并不是C语言代码中的内容,而是给编译器使用的指令。称这类指令为预处理指令。其中include的作用是将后面所指文件复制粘贴过来。
第二行到最后一行是写了main函数的主体。函数在定义时用大括号包裹函数体,即其要执行的指令。C语言程序会默认执行main函数,所以它是一切C程序的入口。
第三行是printf函数,它来自stdio.h这个文件,负责输出内容。
第四行是返回一个值:0
这里我们看出C中的函数的功能和计算机一样,接收一个输入,进行一些指令,然后输出。main函数的返回值即是这个程序运行后的返回值,我们可以将这个返回值拿来判断程序的运行结果。
现在输入编译它的指令
clang first.c
输入ls查看当前目录会看到多了个a.out文件,它即是编译出的可执行文件。
运行它会输出hello world。
现在你已经学会C语言的hello world了