21天学通C语言
第1部分 C语言基础
第1课 初识C语言
欢迎学习本课程!本课将是你成为C程序员高手之路的开始。本课将介绍以下内容:
- 在众多程序设计语言中,为什么C语言是首选
- 程序开发周期中的步骤
- 如何编写、编译和运行第1个C程序
- 编译器和链接器生成的错误消息
1.1 C语言发展简史
读者一定非常好奇C语言的起源及其名字的由来。1972年,丹尼斯·里奇(Dennis Ritchie)在贝尔电话实验室发明了C语言。发明该语言的初衷是为了设计UNIX操作系统(现在用于许多计算机上)。从一开始,C语言就致力于为程序员排忧解难。
C语言因功能强大和灵活,很快便广泛应用于贝尔实验室以外的各领域。世界各地的程序员都开始用它编写程序。不久,各个组织开始使用自己版本的C语言,但是各种版本C语言的实现存在细微差别,这让程序员头疼不已。为解决这一问题,美国国家标准协会(ANSI)于1983年成立了一个委员会,制定了C语言的标准定义,即ANSI C标准。当前的C编译器(极少例外)都支持这个标准。
注意 :C语言极少改动,最新的改动是2011年的ANSI C11标准。该标准在C语言中添加了一些新特性(本书已涵盖)。但是,旧的编译器可能不支持目前的最新标准。
为什么叫C语言? 之所以叫C语言,是因为它的前辈是B语言。B语言由贝尔实验室(Bell Labs)的**肯·汤普逊(Ken Thompson)**发明。至于为什么叫B语言就不言而喻了。
1.2 为何要使用C语言
如今,在计算机程序设计领域,可供选择的高级语言很多,如C、Perl、BASIC、Java、PHP和C#。这些语言都能很好地完成程序设计任务,但是基于以下几个原因,使得C语言仍是众多计算机专业人士的首选:
-
功能强大、十分灵活:你完全想不到C语言能帮你完成什么工作。语言本身不会给你带来任何限制。C语言可用于各种操作系统、文字处理软件、图形、电子表格、甚至是其他语言的编译器。
-
非常流行:是众多专业程序员的首选。因此,市面上很容易找到各种C语言的编译器和辅助工具。
-
可移植性:可移植意味着一台计算机系统(如IBM PC)中写出的C程序,无需修改或少量修改便可在其他操作系统(如DEC VAX系统)中运行。除此之外,在微软Windows操作系统中编写的程序,也可移到Linux系统的机器中(无需修改或少量修改)。ANSI标准进一步改善了C语言的可移植性,为C编译器添加了一系列规则。
-
短小精悍:只包含少量关键字(keyword)。C语言以关键字为基础构建语言的功能,C语言编程离不开关键字。你可能认为一门语言中关键字(有时也称为保留字)越多功能越强大,其实并非如此。
-
模块化:C代码可以(且应该)以例程形式编写,这些例程称为函数(function)。函数可复用于其他程序或应用。通过传递信息给函数,可以创建有用且能重复使用的代码。
正是由于上述特性,使得C语言成为程序设计语言的首选。那C++怎样?你可能在别处了解过C++和面向对象程序设计(object-oriented programming)技术。C与C++有何不同?是否应该自学C++?
别担心!C++是C的超集,这意味着C++中不仅包含了C的所有内容,还添加了面向对象程序设计的新特性。如果你继续学习C++,会发现C中所学的知识几乎都可应用于C++。学习C语言,不仅学了一门现在功能最强大、最流行的程序设计语言,而且还为学习面向对象程序设计做好了准备。
另一门备受关注的语言是Java。Java和C++一样,也是基于C语言发展起来的。如果将来学习Java,你会发现在C语言中学过的所有知识点都用得上。
最新的一门语言是C#(发音为"See-Sharp")。与C++和Java类似,C#也是一门源自C的面向对象语言。同样,在C语言中学到的内容可以直接用于C#程序设计。
注意:许多学过C语言的人,后来都会选择学习C++、Java或C#。先学习C语言,再学其他语言会轻松许多。
1.3 准备编程
解决问题之前肯定要经过一些步骤。首先,必须定义问题。如果不知道问题是什么,根本不可能找到解决方案!知道问题所在,才能设法修正。如果你想到一个解决方案,通常会去实施它。之后,你必须知道问题是否解决了。这样解决问题的逻辑可以应用到各个领域,包括程序设计。
用C语言创建一个程序(或者说,用任意语言编写的计算机程序)时,应该遵循以下步骤的顺序:
- 确定程序的目标------明确你要解决什么问题
- 确定在编程时所使用的方法------规划如何解决问题
- 创建程序解决问题------编写代码实现方案
- 运行程序查看结果------测试并验证解决方案
目标(步骤1) 可能是编写一个文字处理软件或数据库程序。简单的目标可以是在屏幕上显示你的姓名。没有目标就不可能写出程序,因此,如果要写程序就已经准备好第一步了。
接下来,第2步要确定你编写的程序中所使用的方法。你是否需要计算机程序来解决问题?要记录什么信息?程序中要使用什么公式?在这一步中,应该明确自己需要了解什么知识以及实施方案的具体步骤。
例如,假设你要写一个计算圆面积的程序:
- 第1步已经完成,因为目标明确:计算圆的面积。
- 第2步,分析如何确定圆的面积。例如,假设用户提供圆的半径。了解这些以后,便可通过公式π*r²计算得出结果。
现在,可以继续第3步和第4步,进入程序开发周期。
1.4 程序开发周期
程序开发周期的步骤是:
- 使用编辑器创建磁盘文件保存源代码
- 编译源代码创建目标文件
- 链接已编译的代码创建可执行文件
- 运行程序,看看程序是否能按原计划运行
1.4.1 创建源代码
源代码(source code) 是一系列语句或命令,指导计算机执行特定的任务。如前所述,程序开发周期的第1步是编辑器中输入源代码。例如,下面这行C源代码:
c
printf("Hello, Mom!");
这行语句命令计算机在屏幕上显示消息Hello, Mom!(到目前为止,不用管如何执行语句)。
1.4.2 使用编辑器
绝大多数C语言都是在集成开发环境(IDE) 中进行编译的,集成开发环境能让你在它的编辑器中输入程序并编译程序,同时还能调试和创建应用(这些概念今后会学到)。你完全不必使用额外的编辑器。
尽管如此,绝大多数计算机系统仍包含可用作编辑器的程序:
- 如果使用Linux或UNIX系统,可以使用ed、ex、edit或vi编辑器
- 如果使用微软Windows系统,可以使用Notepad或WordPad
大部分文字处理软件都使用特殊的代码格式化文档,在其他程序中无法正确读取这些代码。美国信息交换标准码(ASCII) 几乎为所有的程序(包括C)指定了一个标准文本。许多文字处理软件(如WordPerfect、Microsoft Word、WordPad和WordStar)都能以ASCII形式保存源文件(将源文件作为文本文件而不是文档文件保存)。如果要以ASCII文件保存一个文字处理软件的文件,在保存时必须选择ASCII选项或文本选项。
如果不想用上述编辑器,也可以购买其他的编辑器。市面上有许多专门为输入源代码而设计的软件包(包括商业的和共享软件)。
在保存文件之前必须先给文件命名。文件名应描述该程序的用途。另外,保存C程序的源文件时,文件的扩展名是.c。尽管可以为源文件取任意文件名和扩展名,但是.c是公认较合适的扩展名。
1.4.3 编译源代码
虽然你明白C源代码(至少在学习本书后你会明白),但是计算机不明白。计算机只能理解数字或二进制(binary)的机器语言(machine language)指令。在计算机运行C语言之前,必须先将源代码翻译成机器语言。
这个翻译过程属于程序开发的第2步,由编译器(compiler) 来执行(编译器也是一个程序)。编译器将源代码作为输入,生成磁盘文件,其中包含源代码相应的机器指令。编译器创建的机器语言指令被称为目标代码(object code) ,包含目标代码的文件称为目标文件(object file)。
注意 :本书涵盖ANSI C标准,这意味着只要编译器遵循ANSI标准,你可以使用任意编译器进行编译。然而,并非所有的编译器都支持该标准。当前的C语言标准名为ISO/IEC 9899:2011 。为简单起见,本书在提到该标准时均用C11代替复杂的标准名。
使用图形集成开发环境来编译程序非常简单。在大多数图形环境中,通过选择"编译"图标或相应的菜单选项即可编译程序清单。在编译代码后,选择"运行"图标或相应的菜单选项来执行程序。在使用编译器之前,应先查看编译器的用户手册,了解编译器编译和运行程序的规范。
Code::Blocks就是一个图形开发环境,有各种操作系统的版本,可免费下载。除此之外,还有许多适用于多平台的其他图形开发环境,读者可依自己喜好免费下载或购买。
编译完成后,生成一个目标文件。如果查看编译目录或文件夹中的文件列表,会发现一个与源文件同名的文件,但是扩展名是.obj(不是.c)。扩展名为.obj的文件是目标文件,供链接器使用。在Linux和UNIX系统中,编译器生成的目标文件扩展名是.o,不是.obj。
1.4.4 链接以创建可执行文件
在运行程序之前,还要完成一步。函数库 是ANSI C语言定义的一部分,其中包含了预定义函数的目标代码(已编译过的代码)。预定义函数(predefined function) 包含已编写好的C代码,在编译器的软件包中可随时使用。
1.4.1节中使用的printf()函数就是一个库函数(library function) 。库函数用于执行一些经常需要完成的任务(如,在屏幕上显示信息、从磁盘文件中读取数据等)。如果在程序中使用了这些函数(几乎所有的程序都需要使用库函数),必须将编译源文件时生成的目标文件与库函数的目标文件合并,创建最终的可执行程序(可执行的意思是,可以在计算机上运行或执行程序)。上述过程称为链接(link) ,执行这一过程的程序称为链接器(linker)。
计算机 --> 使用编辑器 --> 源代码 --> 编译源代码 --> 目标代码
↓
库文件 链接目标文件 --> 可执行文件
1.4.5 完成开发周期
程序经过编译和链接将创建一个可执行文件,点击"运行"按钮即可运行该文件(假设在集成开发环境中进行操作)。如果运行程序后得到的结果与预期不符,则需要回到第1步。必须找出问题所在,并更正源代码。一旦改动了源代码,就要重新编译和重新链接程序,以创建更正后的可执行文件。重复这个过程直至程序的执行情况与预期相符。
关于编译和链接还要注意一点,虽然本书将编译和链接分成两个独立的步骤来讲解,但是大多数编译器都将其合为一个步骤。通常,图形开发环境会提供一个选项,让用户设置是分开完成编译和链接还是一步完成。无论以哪种方式完成编译和链接,都要明白,即使只使用一条命令来完成编译和链接,它们仍是两个独立的行为。
C程序的开发周期如下:
| 步骤 | 操作 | 输入 | 输出 | 说明 |
|---|---|---|---|---|
| 1 | 使用编辑器编写源代码 | 想法和算法 | 源代码文件(.c) | 传统上,C源代码文件的扩展名是.c(如myprog.c、database.c) |
| 2 | 使用编译器编译程序 | 源代码文件(.c) | 目标文件(.obj或.o) | 如果编译器发现错误会报错。必须返回步骤1,在源代码中更正错误 |
| 3 | 使用链接器链接程序 | 目标文件 + 库文件 | 可执行文件(.exe) | 如果不出错,链接器将创建可执行程序 |
| 4 | 执行程序 | 可执行文件 | 程序运行结果 | 测试程序,判断它是否如期正常运行。如果不是,返回步骤1 |
除最简单的程序外,在完成程序前,几乎所有的程序都要按顺序执行这些步骤多次。即使是经验丰富的程序员也不可能一蹴而就,写出没有任何错误的程序!因为要多次重复编辑-编译-链接环节,所以必须熟悉你所使用的工具:编辑器、编译器和链接器。
1.5 第1个C程序
按以下步骤输入和编译hello.c程序。
推荐开发环境:
- Dev C++
- VS Code
- Visual Studio 2022/2025
- Code::Blocks
- CLion
第一个C程序:hello.c
c
#include <stdio.h>
int main(void) {
printf("Hello, World!\n");
return 0;
}
程序解释:
#include <stdio.h>:包含标准输入输出头文件,让程序可以使用printf()等函数int main(void):程序的主函数,每个C程序都必须有且只有一个main函数{ }:花括号内是函数体,包含要执行的语句printf("Hello, World!\n");:在屏幕上显示"Hello, World!",\n表示换行return 0;:函数返回值,0表示程序正常结束
编译运行步骤:
- 打开你选择的IDE
- 创建新项目或新文件
- 输入上面的代码
- 保存文件为
hello.c - 点击编译按钮(通常是一个齿轮或锤子图标)
- 点击运行按钮(通常是绿色三角形)
如果一切正常,你将在控制台看到输出:Hello, World!
1.6 小结
本章介绍了C语言的基础知识,为后续学习奠定了坚实的基础。我们学习了:
- C语言的历史:从贝尔实验室的丹尼斯·里奇发明C语言,到ANSI标准化,再到今天的C11标准。
- 为什么选择C语言:因其功能强大、流行、可移植、简洁和模块化等优点。
- 编程准备:明确问题、规划方案、编写代码、测试结果的四步法。
- 程序开发周期:编辑->编译->链接->测试的循环过程。
- 第一个C程序:编写并运行了经典的"Hello, World!"程序。
C语言不仅是学习编程的绝佳起点,也是理解计算机底层工作原理的重要工具。掌握C语言后,学习其他语言(如C++、Java、C#)将更加容易。
1.7 答疑
问:如果要将自己编写的程序提供给他人,应提供哪些文件?
答:通常只需要提供**可执行文件(.exe)**即可。但是,如果你希望他人能够修改或学习你的代码,应该提供:
- 源代码文件(.c文件)
- 头文件(.h文件,如果有的话)
- 项目文件(如果使用IDE)
- 使用说明文档
如果程序依赖于特定的库,还需要提供相关信息或动态链接库(DLL)。
问:创建可执行文件后,是否还要保留源代码或目标代码?
答:强烈建议保留源代码,因为:
- 未来可能需要修改或升级程序
- 调试时需要参考源代码
- 学习或教学目的
- 作为个人项目作品集的一部分
目标文件(.obj/.o)通常可以删除,因为它们可以从源代码重新生成。但是,在大型项目中,保留目标文件可以加快编译速度(增量编译)。
问:如果只有C++编译器没有C编译器,怎么办?
答:大多数C++编译器都可以编译C代码,但需要注意:
- 将文件扩展名改为.cpp可能使编译器按C++规则编译
- 最好保持.c扩展名,并在编译器设置中指定按C语言编译
- C++是C的超集,但有一些细微差别:
- C++要求函数原型,C不强制
- C++中
const变量的处理方式不同 - C++有更严格的类型检查
- 使用
extern "C"链接说明符可以确保C++正确处理C函数
问:是否可以忽略警告消息?
答:不推荐忽略警告消息,因为:
- 警告通常是潜在问题的指示器
- 某些警告可能预示着未定义行为
- 在调试阶段,警告可以帮助发现逻辑错误
- 良好的编程习惯是处理所有警告,使程序"零警告"编译
但是,在某些情况下,如果确定警告不影响程序正确性,并且是由于编译器过于严格导致的,可以使用编译器选项暂时禁用特定警告。例如,在GCC中使用-Wno-xxx选项。
1.8.1 简答题
-
简述C语言的发展历史及其名称的由来
C语言由丹尼斯·里奇于1972年在贝尔实验室发明,最初用于开发UNIX操作系统。它的名称来源于其前身B语言(由肯·汤普逊发明),B语言本身又源自BCPL语言。
-
列举至少三个选择C语言而不是其他高级语言的理由
(1) 功能强大且灵活,几乎可用于任何编程任务
(2) 可移植性好,同一代码可在不同平台运行
(3) 执行效率高,接近汇编语言的性能
(4) 为学习其他语言(C++、Java、C#)打下坚实基础
-
描述程序开发周期的四个主要步骤
(1) 编辑:使用文本编辑器编写源代码(.c文件)
(2) 编译:使用编译器将源代码转换为目标代码(.obj/.o文件)
(3) 链接:使用链接器将目标代码与库文件合并生成可执行文件(.exe文件)
(4) 测试:运行可执行文件,验证程序功能
-
解释编译器和链接器在程序开发中的作用
编译器将人类可读的源代码翻译成机器可执行的目标代码,检查语法错误;链接器将多个目标文件及库文件组合成单一的可执行文件,解析外部引用和函数调用。
-
为什么说学习C语言有助于学习C++、Java等其他语言?
因为C++、Java、C#等现代编程语言都深受C语言影响,共享相似的语法结构、控制流程和编程概念。C语言的核心思想(如指针、内存管理)在这些语言中都有体现或变体。
-
什么是ANSI C标准?为什么它很重要?
ANSI C标准是美国国家标准协会制定的C语言规范,确保不同编译器生成的代码具有一致性和可移植性。它很重要因为它定义了C语言的核心特性,使程序员可以编写跨平台的代码。
1.8.2 练习题
-
环境配置练习
下载并安装一个C语言开发环境(如Code::Blocks、Dev C++或VS Code的C/C++扩展),配置编译器路径,确保能够成功编译和运行C程序。
-
第一个程序修改
修改"Hello, World!"程序,使其显示以下内容:
==================== 欢迎学习C语言编程! 这是第1章的学习内容 作者:[你的名字] ==================== -
编译错误调试
故意在程序中制造以下错误,观察编译器的反应:
- 删除
#include <stdio.h> - 将
main拼写为mian - 删除语句末尾的分号
- 删除一个花括号
记录每种错误对应的错误消息,并理解其含义。
- 删除
-
多文件编译练习
创建两个源文件:
main.c包含main函数,调用print_message()函数message.c包含print_message()函数,显示一条消息
分别编译这两个文件,然后链接它们生成可执行程序。
-
程序结构分析
分析以下程序,预测其输出,然后实际运行验证:
c#include <stdio.h> int main(void) { printf("Line 1\n"); printf("Line 2\n"); printf("Line 3"); printf(" still Line 3\n"); printf("Line 4\n"); return 0; }注意
\n换行符的作用和多个printf语句在同一行的效果。 -
扩展练习:简单计算器
编写一个程序,计算并显示以下内容:
- 半径为5.0的圆的面积(公式:π*r²,π取3.14159)
- 边长为3和4的矩形的周长
- 1到10的整数和
程序输出格式如下:
圆面积:78.53975 矩形周长:14 1到10的和:55
学习建议:
- 实际动手敲代码,不要只看不练
- 遇到错误时仔细阅读错误信息,学会自己排查问题
- 养成写注释的好习惯,解释代码的意图
- 尝试修改示例代码,观察不同的效果
- 加入编程社区,参与讨论和分享
学习编程就像学习游泳,只有跳进水里才能真正学会。不要害怕犯错,每个程序员都是从"Hello, World!"开始的。祝你学习愉快,编程之路一帆风顺!