前言
这个脑图会让你对C语言有一个整体的把控。包括以下主题:
- C语言历史
- C语言简介
- 变量和类型
- 常量
- 操作符
- 分支
- 循环
- 数组
- 字符串
- 指针
- 函数
- 输入输出
- 变量作用域
- 静态变量
- 枚举类型
- 结构
- 命令行参数
- 头文件
- 注释
C语言历史
20世纪60年代,贝尔实验室的研究员Ken Thompson(肯·汤普森)发明了B语言,并使用B语言编写了一个游戏:Space-Travel,Thompson的同事D.Ritchie(丹尼斯.里奇)也想要玩Space Travel,所以加入了Ken Thompson,合作开发,他的主要工作是改进Thompson的B语言,取名为:C语言。
C简介
C语言是最广为人知的编程语言,根据TIOBE编程语言排行榜,C语言目前仍然是使用人数最多的编程语言之一。国内外很多大学都将C,Python或者Java作为相应学科的主修课程。C语言是最接近于底层硬件的高级语言,可以帮助我们从硬件架构的角度来思考问题。C语言的优势在于效率非常高,所以在芯片开发,操作系统等对于执行速度和实时性有比较高要求的场景中,C的使用非常广泛。和Python,Java等语言相比,C语言的缺点在于内存管理容易出错。
C语言是我学习的第一门编程语言。C语言的书很薄,基础语法很简单,但是想用好C语言成为高手却需要花费很多功夫,因为C语言偏底层,和硬件打交道,思维方式偏硬件,而且有很多细节需要注意。
C语言的应用范围很广,比如Android手机的底层是Linux操作系统,Linux就是用C语言写的。各种芯片中的固件或者驱动程序,大多是用C写的。嵌入式设备,音视频编解码等领域C语言用的也比较多。原因在于,这些领域对于程序的执行效率有很高的要求。
为什么这些底层的软件要用C语言来写呢?因为C写出来的程序性能和效率都很高。 举个例子,做手机基带芯片开发,负责手机和基站的通信。C语言写的代码,体积很小,所以芯片可以使用更小的 ROM(大家可以把ROM理解为硬盘)来存储代码。假设因为使用的ROM小,可以节省一毛钱的成本,我们公司的芯片出货量是 10 亿级别的。那么我们可以创造出1亿的利润。这就是量变引起质变,为什么芯片开发需要用C语言的原因。并且芯片内部有很多的数值运算,C的运算效率也是最高的。
我们最熟悉的数学使用的是10进制,数字由0到9组成。表示更大的数值,我们就需要使用多个数字组合起来。比如19,190等等。大家想一想,我们可以将思维延伸一下,既然可以用 0~9 一共十个数字来表示数值,那么也可以用0、1两个数字来表示数值,这就是二进制。比如,数字 0、1、10、111、100、1000001 都是有效的二进制。
- 二进制加减法和十进制加减法的思想是类似的: 1、对于十进制,进行加法运算时逢十进一,进行减法运算时借一当十;2、对于二进制,进行加法运算时逢二进一,进行减法运算时借一当二。
我们需要明确一点:我们使用的电子设备都是2进制的,CPU只认识二进制的 01 码,比如 01011100。这种二进制 01 码对于我们程序员写代码和阅读代码都非常困难,所以大牛们发明了各种编程语言,使用人类容易读懂的字符进行程序编写。这就是编程语言的由来。不同的编程语言最终都要转换成机器能够识别的二进制,交给机器执行。这是一个翻译的过程。
- 编程语言有两种,一种是编译型语言,比如 C,Java,Go。另一种是解释型语言,比如 Python,JavaScript
PS:不管是编译型语言还是解释型语言,最终都需要把程序员写的代码翻译成二进制机器代码,交给机器执行。它们的区别在哪呢? 编译型语言会先将写好的代码通过编译器,一次性全部编译成二进制文件,然后交给机器执行。 解释型语言的执行过程是一边解释一边执行,一条一条来。 编译型语言的好处是,已经事先翻译成了机器认识的代码,所以执行效率高,速度快。但是需要事先编译,我们每次写完代码都要编译一遍才能运行,有时候编译的时间很长,需要几分钟,甚至超过一个小时。 解释型语言的好处是,写完代码之后直接执行,不需要等待编译。但是缺点是执行效率低,代码跑得慢。因为每一次运行代码,要一边翻译一边执行。
大家可以想象一下,比如咱们有个程序需要运行 100 次。那么对于编译型语言来说,只需要编译一次,后面都是直接运行。解释型语言每次执行时都要同步的一边翻译一边执行。所以编译型语言整体上效率要高。
C语言没有垃圾回收。这意味着我们必须自己管理内存的分配和使用。这就是 C 当中的指针。指针操作非常复杂,程序员需要相当小心,以防止错误。即便是像我一样的老司机程序员也有可能在使用指针时犯错误。C这种手动管理内存,容易出错。但是也有好处,就是C的效率很高,这就使得C是理想的编写物联网设备软件的语言,可以用在 Arduino 之类的平台。
总体来说,C语言的特点是把主动权交给用户,灵活性很高,C并没有隐藏机器的各项能力和复杂性。一旦你精通C语言,你就可以可以精确地控制硬件,能力很强,性能超高,不过也容易出问题:)
拿做饭打比方,C语言就好比是菜刀,什么形状都能切,便宜并且效果还不错。但是有可能会伤手。其他的高级语言就好比高级一些的厨房里面的各种复杂工具,能够很方便的帮我们切出胡萝卜丝,土豆丝,在特定领域很方便,但是不够灵活。
- 下面进入正题,大家写的第一个程序都是 Hello World。这个程序很简单,目标是在屏幕上打印出一句话:hello world。我们通过它来了解代码的基础知识。
#include <stdio.h> int main(void) { printf("Hello, World!"); }
我们看一下这个源代码:我们在第一行首先导入stdio库(stdio是standard input output的意思,代表标准输入输出库)。这个库允许我们访问输入/输出功能。也就是这里我们需要用到的printf,把hello world打印出来。
C语言的核心模块很小。非核心的功能都由各种库来提供,就好比厨房装修好了之后就有了做饭的基本条件,有灶台,抽油烟机等。但是我们想要做一桌大餐,我们还需要电饭煲来做米饭,烤箱来烧烤等等工具。这些工具就相当于库,它们提供了C语言核心框架不具备的能力。这些库分为两种:
- 一些库由普通程序员编写,提供给其他程序员使用。
- C 的编译器中内置了一些库。就像stdio这种。
stdio库为我们提供了printf打印函数。这个函数是被包裹在main函数当中的,所有的C语言程序都是从main函数开始执行。
函数
这里出现了一个概念:函数。那什么是函数呢?
函数是组织好的,可重复使用的,用来实现单一或者相关联功能的代码段。这个是鬼话,不好理解。换成人话就是:函数就是一个功能模块。你给他提供一些输入,它完成相关的操作,然后给你返回一个结果。函数的核心就三个步骤,输入,操作,输出。
比如你放一些水和米到电饭煲,过阵子它就做好一锅米饭返回给你了。函数的特点是可以重复使用,你每天都能用电饭煲做米饭。我们使用函数的人,可以不用关心函数的实现细节,只需要知道给他什么输入,它完成什么功能,给你返回什么输出就成了。
用这里的main函数举例。main是它的名字,我们想要用函数的时候,就是通过这个名字来调用函数的。名字之前有一个int,表示函数的返回值是一个整数(integer)。名字之后有一个括号,括号中是这个函数需要接收的参数,这里void表示不需要参数。如果需要两个整型参数,我们就可以写成int max(int a, int b)参数之后是大括号,大括号中是函数的主体,也就是这个函数要干什么。在这个 main 函数中,就是调用 printf 打印 hello world。
所以大家记住函数的四个要素:
- 函数名
- 返回值:在函数名之前
- 参数:函数名之后的括号中
- 函数主体:参数后的大括号中
这里需要提醒的是,有些同学可能觉得英文不好,该怎么学呢?我的建议是遇到一个不会的英文单词,就搞懂一个。比如这里,你需要搞懂 main,int,include,void 分别是什么意思。一点一点把必须掌握的英文搞定就好了。不需要一下子去背很多单词。
大家注意看这里printf()函数的编写方式和刚才的main函数不同。它没有定义返回值,我们只是在括号中写了一个字符串作为参数,同时我们没有具体说明参数的类型。这是因为刚才的main函数是函数定义。而这里是一个函数调用。printf 的函数定义在 stdio 库中,像这样:
int printf(const char *format, ...);
这样是不是就明白了。函数分为函数定义和函数调用。我们首先要定义一个函数,有了定义之后,才能调用函数。就好像你必须先造出来一个电饭煲,才能使用电饭煲做米饭。
定义函数时,有四要素。大家可以在返回之前的讲解复习一下,调用时,就直接用就好了。目前不需要太纠缠细节,理解大概就成。
#include <stdio.h>
int main(void) {
printf("Hello, World!");
}
上面是我们main函数的定义,当我们执行程序时,main函数会在操作系统当中被调用。
那么我们如何去执行程序呢?
就像我们前面所讲的,C 语言是一种编译语言。要运行程序,我们必须首先编译它。任何 Linux 或 macOS 计算机都内置了C编译器。对于 Windows 用户,大家可以使用 Windows Subsystem for Linux (WSL)就是 windows 当中的 Linux。或者使用 VC 之类的工具。
我们首先打开一个终端,然后输入gcc。这时应该会返回一个错误,说我们没有指定文件,这就说明我们已经安装了 gcc,可以开始编程了。这里给大家提醒一下,一般我们编程都会遇到错误,错误提示都是英文的,我们怎么办呢?把这个英文拷贝下来,打开 bing,搜翻译。贴进去。整体来讲,翻译质量还是可以的。这样我们就能知道到底出了什么问题。但是只是知道出了什么问题,并没有解决问题,怎么办呢?
在搜索引擎搜索这句话,懂英文的可以上 stackoverflow,不懂英文的,可以上知乎,segmentfault,V2EX 等网站搜索,总能找到解决方案。
C语言简介
变量
常量
运算符
分支
循环
数组
字符串
指针
函数
输入输出
作用域
静态变量
typedef
结构
命令行参数
头文件
- 感谢来自溢出君的图片支持