01. 初识C语言
一、C语言简介
1.1、什么是C语言
C 语言是一门 面向过程 的、抽象化 的通用程序设计语言,广泛应用于 底层开发。C 语言能以简易的方式编译、处理低级存储器。C 语言是仅产生少量的机器语言以及不需要任何运行环境支持便能运行的高效率程序设计语言。尽管 C 语言提供了许多低级处理的功能,但仍然保持着跨平台的特性,以一个标准规格写出的C语言程序可在包括类似嵌入式处理器以及超级计算机等作业平台的许多计算机平台上进行编译。
1.2、C语言的起源
C 语言诞生于美国的贝尔实验室,由 丹尼斯.里奇(Dennis Ritchie)以 肯尼斯·蓝·汤普森(Kenneth Lane Thompson)设计的 B 语言为基础发展而来,在它的主体设计完成后,汤普森和里奇用它完全重写了 UNIX,且随着 UNIX 的发展,C 语言也得到了不断的完善。
1.3、C语言的标准
C 语言发展之初,并没有所谓的 C 标准。1978年,布莱恩.柯林汉(Brian Kernighan)和 丹尼斯.里奇(Dennis Ritchie)合著的 The C Programming Language(《C语言程序设计》)第一版是公认的 C 标准,通常称之为 K&R C 或 经典C。
随着 C 的不断发展,越来越广泛地应用于更多系统中,C 社区意识到需要一个更全面、更新颖、更严格地标准。鉴于此,美国国家标准协会(ANSI)于 1983年 组建了一个委员会(X3J11),开发了一套新标准,并于 1989年 正式发布。该标准(ANSI C)定义了 C 语言和 C 标准库。国际标准化组织于 1990年 采用了这套 C 标准(ISO C)。ISO C 和 ANSI C 是完全相同的标准。ANSI/ISO 标准的最终版本通常叫做 C89(因为 ANSI 于 1989年 批准该标准)或 C90(因为 ISO 于 1990年 批准该标准)。
1994年,ANSI/ISO 联合委员会(C9X委员会)开始修定 C 标准,最终发布了 C99 标准。该委员会遵循了最初 C90 标准的原则,包括保持语言的精炼简单。委员会的用以不是在 C 语言中添加新特性,而是为了达到新的目标。但是,供应商并未像对 C90 那样很好地接受和支持 C99。
标准委员会在 2007年 承诺 C 标准的下一个版本是 C1X,2011年 终于发布 C11标准。因为,供应商并未像对 C90 那样很好地接受和支持 C99,这使得 C99 中的一些特性称为 C11 的可选项。
1.3、C语言的语言特点
C 语言是一种 结构化语言,它有着清晰的层次,可按照模块的方式对程序进行编写,十分有利于程序的调试,且 C 语言的处理和表现能力都非常的强大,依靠非常全面的运算符和多样的数据类型,可以轻易完成各种数据结构的构建,通过指针类型更可对内存直接寻址以及对硬件进行直接操作,因此既能够用于开发系统程序,也可用于开发应用软件。
1.3.1、C语言的优点
【1】、简洁的语言
C 语言包含的各种控制语句仅有 9 种,关键字也只有 32 个,程序的编写要求不严格且以小写字母为主,对许多不必要的部分进行了精简。实际上,语句构成与硬件有关联的较少,且 C 语言本身不提供与硬件相关的输入输出、文件管理等功能,如需此类功能,需要通过配合编译系统所支持的各类库进行编程,故 C 语言拥有非常简洁的编译系统。
【2】、具有结构化的控制语句
C 语言是一种结构化的语言,提供的控制语句具有结构化特征,如 for 语句、if...else 语句 和 switch 语句等。可以用于实现函数的逻辑控制,方便面向过程的程序设计。
【3】、丰富的数据类型
C 语言包含的数据类型广泛,不仅包含有传统的字符型、整型、浮点型、数组类型等数据类型,还具有其他编程语言所不具备的数据类型,其中以指针类型数据使用最为灵活,可以通过编程对各种数据结构进行计算。
【4】、丰富的运算符
C 语言包含 34 个运算符,它将赋值、括号等均视作运算符来操作,使 C 程序的表达式类型和运算符类型均非常丰富。
【5】、可对物理地址进行直接操作
C 语言允许对硬件内存地址进行直接读写,以此可以实现汇编语言的主要功能,并可直接操作硬件。C 语言不但具备高级语言所具有的良好特性,又包含了许多低级语言的优势,故在系统软件编程领域有着广泛的应用。
【6】、代码具有较好的可移植性
C 语言是面向过程的编程语言,用户只需要关注所被解决问题的本身,而不需要花费过多的精力去了解相关硬件,且针对不同的硬件环境,在用 C 语言实现相同功能时的代码基本一致,不需或仅需进行少量改动便可完成移植,这就意味着,对于一台计算机编写的 C 程序可以在另一台计算机上轻松地运行,从而极大的减少了程序移植的工作强度。
【7】、可生成高质量、目标代码执行效率高的程序
与其他高级语言相比,C 语言可以生成高质量和高效率的目标代码,故通常应用于对代码质量和执行效率要求较高的嵌入式系统程序的编写。
1.3.2、C语言的缺点
C 语言的缺点主要表现为 数据的封装性弱,这一点使得 C 在数据的安全性上有很大缺陷,这也是 C 和 C++ 的一大区别。
C 语言的语法限制不太严格,对变量的类型约束不严格,影响程序的安全性,对数组下标越界不作检查等。从应用的角度,C 语言 比其他高级语言较难掌握。也就是说,对用 C 语言的人,要求对程序设计更熟练一些。
C 语言相对于 Java、Python 等编程语言而言,它的可移植性较差,它对平台的依赖较多。
1.4、C语言的应用领域
C 语言的应用及其广泛,从网站后台开发,到底层操作系统,从多媒体应用到大型网络游戏,均可使用 C语言 来开发。
- C 语言可以写网站后台程序
- C 语言可以专门针对某个主题写出功能强大的程序库
- C 语言可以写出大型游戏的引擎
- C 语言可以写出另一个语言
- C 语言可以写操作系统和驱动程序
- 任何设备只要配置了微处理器,就都支持 C 语言
二、开发环境搭建
2.1、环境搭建
C 语言的开发环境有多种,我们可以使用微软开发的 Visual Studio 来开发 C 语言程序,也可以采用 gcc + 文本编辑器 的方式来开发 C 语言程序。
MinGW,是 Minimalist GNU for Windows 的缩写。它是一个可自由使用和自由发布的 Windows 特定头文件和使用 GNU 工具集导入库的集合,允许你在 GNU/Linux 和 Windows 平台生成本地的 Windows 程序而不需要第三方 C 运行时(C Runtime)库。我们可以通过以下链接下载 MinGW:https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/8.1.0/threads-posix/seh/?tdsourcetag=s_pctim_aiomsg
【1】、version
Version:指的是 gcc 的版本,如果没有特殊的需求,一般选择最高的版本号即可。
【2】、Architecture
Architecture:电脑系统是 64位 的,选择 x86_64;如果是 32位 系统,则选择 i686。
【3】、Threads
Threads:如果是 Windows,可以选择 win32,也可以选择 posix。如果是 Linux、Unix、Mac OS 等其他操作系统要选择 posix。
【4】、Exception
Exception:seh 是新发明的,而 sjlj 则是古老的。seh 性能比较好,但不支持 32位。 sjlj 稳定性好,支持 32位。
建议64位操作系统选择 seh。
由于使用在线安装程序安装 MinGW 总是出错,建议直接下载对应版本的免安装的压缩包使用;
2.2、配置环境变量
右键此电脑图标,选中属性选项,在弹出的菜单中选择高级系统设置。选择高级选项,点击环境变量,在弹出的选项卡,选中 Path 属性,点击编辑,在弹出的选项卡中点击新建按钮,将 MinGW 安装目录的的 bin 目录添加到 Path 属性值中。
在配置环境的变量的时候,会有两个环境变量,上面的是当前用户的用户变量,下面的是系统的变量。用户变量只针对当前用户起作用,系统变量对全部用户都起作用,对于个人电脑来说,用户变量和系统变量的差别不大;
2.3、配置VSCode
这里,我们使用 VSCode 运行编写好的 C 语言代码,我们需要安装对应的插件。这里,推荐使用微软提供的 C 语言开发包,也可以使用其他开发者提供的插件使用,例如:Code Runner。
2.4、简易的C语言程序
用 C语言 编写程序时,编写的内容被存储在文本文件中,该文件被称为 源代码文件(source code file)。大部分 C系统,都要求文件名以 .c 结尾。在文件名中,点号(.)前面的部分称为 基本名(basename),点号后面的部分称为 扩展名(extension)。基本名与扩展名的组合就是文件名。文件名应该满足特定计算机操作系统的要求。
C 语言是从主函数的第一行开始执行的,所以 C 语言代码中得有 main() 函数。
#include <stdio.h>
int main(void)
{
printf("hello world!\n");
return 0;
}
2.5、C语言的编译过程
C 编程的基本策略是,用程序把源代码文件转换为可执行文件(其中包含可直接运行的机器语言代码)。典型的 C 实现通过 编译 和 链接 两个步骤来完成这一过程。编译器把源代码转换为中间代码,链接器把中间代码和其它代码合并,生成可执行文件。
C 使用这种分而治之的方法方便对程序进行模块化,可以独立编译单独模块,稍后在用链接器合并已编译的模块。通过这种方式,如果只是更改某个模块,不必因此重新编译其它模块。另外,链接器还将你编写的程序和预编译的代码块合并。
中间文件有多种格式,这里只描述一种普遍的形式,即把源代码转换为机器语言代码,并且结果放在 目标代码文件(简称目标文件) 中(这里源代码只有一个文件)。虽然目标文件中包含机器语言代码,但是并不能直接运行该文件。这是因为,目标文件中存储的是编译器翻译的源代码,这还不是一个完整的程序。
目标代码文件缺失 启动代码(startup code)和 库函数。启动代码充当着程序和操作系统之间的接口。几所所有的 C 程序都要使用 C 标准库中的函数。库文件中有许多函数的额目标代码。
链接器的作用是,把你编写的 目标代码、系统的标准启动代码 和 库函数 这 3 部分合并成一个文件,即 可执行文件。对于库函数,链接器 之后把程序中要用到的库函数提起出来。
简而言之,目标文件和可执行文件都有机器语言执行组成。然而,目标文件中只包含编译器为你编写的代码翻译的机器语言代码,可执行文件中还包含你编写的程序中使用的库函数和启动代码的机器代码。
C 语言编译成可执行程序经过 4 步:
- 预处理:宏定义展开、头文件展开、条件编译等,同时将代码中的注释删除,这里并不会检查语法;
- 编译:检查语法,将预处理后文件编译生成汇编文件;
- 汇编:将汇编文件生成目标执行文件(二进制文件);
- 链接:C 语言写的程序是依赖各种库的,所以编译之后还需要把库文件链接到最终的可执行程序中。
gcc 分步编译过程:
编译过程 | gcc 命令 | 示例 |
---|---|---|
预处理 | gcc -E 源文件 -o 预处理后的C语言文件.i | gcc -E template.c -o template.i |
编译 | gcc -S 预处理后的C语言文件.i -o 汇编文件.s | gcc -S template.i -o template.s |
汇编 | gcc -c 汇编文件.s -o 二进制文件.o | gcc -c template.s -o template.o |
链接 | gcc 二进制文件.o -o 目标生成文件 | gcc template.o -o template.exe |
各个命令参数的含义:
选项 | 含义 |
---|---|
-E | 只进行预处理 |
-S | 只进行预处理和编译 |
-c | 只进行预处理、编译和汇编 |
-o file | 指定生成的输出文件名为 file |
文件后缀含义:
文件后缀 | 含义 |
---|---|
.c | C语言 源文件 |
.i | 预处理后的 C语言 文件 |
.s | 编译后的汇编文件 |
.o | 编译后的目标文件 |
我们可以通过
gcc -o 生成的目标程序 源代码文件
一步编译 C语言 程序,例如:gcc -o template.exe template.c
2.6、VSCode运行C语言程序
编写好 C 语言程序后,我们可以在 VSCode 中运行程序。