《C Primer Plus》- 第二章 C语言概述
本笔记写于2020年1月27日。
本系列文章参考的是《C Primer Plus》(第六版),其中里面会有笔者自己的相关补充。
以下示例均运行于macOS Catalina 10.15.2上,编译器为clang 11.0.0
PS:如果笔记中有任何的错误,请在下方评论中留言,我会及时回复并修改,谢谢
简单的C示例
首先来看一个非常简单的C程序示例
#include <stdio.h>
int main(void)
{
int num;
num = 1;
printf("I am a simple ");
printf("computer.\n");
printf("My favorite number is %d because it is first.\n", num);
return 0;
}
结果如下:

解析
上述示例看似简单,但也基本展示了C程序的方方面面。本节将详细解释其中的每一行代码
#include和头文件
第一行#include <stdio.h>
是一条预处理指令。在第一章笔记的最后一幅图中,可以看到编译器将源代码文件编译为了目标文件,而实际上在编译操作执行前,编译器会对源代码文件进行一些处理操作,这些操作被称为预处理。(有关预处理器的更多知识请看第十六章的笔记)
#include
语句是一个文件引用的预处理指令,意思是将stdio.h
文件中的所有内容复制到#include <stdio.h>
的所在区域,实质上是一种“复制-粘贴”的工作。
引用的文件stdio.h
则是C语言的标准库文件之一,该文件中包含了C语言常用的输入输出函数,如:示例中使用的printf函数。由于这类文件常常是在C语言代码文件的头部引用,因此也被称为头文件。
笔者补充:截止到2020年1月27日,C语言共包含标准库文件29个,其中包括C11标准中新增的5个

main函数
int main()
C程序包含一个或多个函数,函数是C程序的基本模块。而示例第二行的main()
函数,则是C程序的开始函数,所以的C程序都是从main()
函数开始的。我们还可以定义很多其他的函数,但main()
函数一定是开始函数。程序在执行时首先会寻找main()
函数,然后依次执行函数中的语句。
圆括号()
表明了main()
是一个函数,而不是一个其他什么东西;int
是main()
函数的返回类型,表明main()
函数返回的值是整数;括号中的void
表明该函数的参数为空。(有关函数的更多的知识可以查看第九章的笔记)
笔者补充:main函数不一定是C程序的开始函数,只不过绝大部分的C语言编译器都以
main()
函数作为默认的程序入口点。我们可以通过一定的方法修改C程序的开始函数,如果有时间,笔者会专门写一篇这个笔记来介绍。
注释
上述示例中由于偷懒,笔者没有写注释,这里说一下。
C语言注释共有两种
- 多行注释:这是C语言原本的注释形式,程序中被
/* */
符号括起来的部分就是程序的注释
/* 有效的注释 */
/* 分成了两行,
也是有效的注释 */
/*
有效的注释
*/
/* 无效的注释,因为缺少了结束标记
- 单行注释:C99标准新增,以
//
开始,在双斜线后面处于同一行的所有内容都是程序的注释
// 有效的注释
int num; // 也可以写在这里
花括号、函数体和块
所有的C函数都使用花括号标记函数的开始和结束,而且,只有花括号({}
)可以标记,圆括号(()
)和方括号([]
)都不行。同时,花括号还可以用于把函数中的多条语句合并为一个单元或块。
声明
声明是C语言最重要的特性之一。示例中的int num;
语句是一条声明变量语句,它完成了两个工作:
在函数中有一个名为num的变量
num变量的类型是
int
类型,即整数类型
语句末尾的分号表明该语句已经结束,C语言以分号;
作为语句结束的标志。
关键字和标识符
语句中的int
是C语言的关键字,它表示了一种基本数据类型(关于基本数据类型请看第三章笔记)。关键字是语言定义的一种具有特定用途的单词,不能用作其他用途。截止到2020年1月17日,C语言中共包含了44个关键字。
语句中的num
是一个标识符,它表示了一个变量、函数或其他实体的名称。通过标识符,程序将计算机内存中的特定位置与一个名称联系起来,也确定了存储在该特定位置的信息类型或数据类型。
标识符有以下需要注意的地方:
标识符应该要使用有意义的名称,使人望文生义。同时,如果标识符本身无法清楚的表达自身的用途,可以在注释中进行进一步的阐述
在C语言中,标识符是区分大小写的,也就是说
num
和Num
是两个不同的标识符标识符中可以包括小写字母、大写字母、数字和下划线,但名称的第一个字符必须是字符或下划线,不能是数字
不能使用关键字作为标识符,因为关键字已经有了其他用途了。同理,C语言中还存在有一些保留标识符(包括以下划线开头的部分标识符标准库函数名)也不应该作为标识符使用
赋值操作
赋值是C语言的基本操作之一。在介绍标识符中曾提到过,通过标识符,程序将计算机内存中的特定位置与一个名称联系起来。但之前的声明仅仅是告诉编译器要在内存中预留出这块空间来,并将这块空间与对应标识符联系起来,并没有使用这块空间。
赋值操作便是使用空间的一种方法。示例中num = 1;
表示将数字1放入变量num
对应的预留空间中,同时,还可以对该空间进行多次赋值,因此,num
被叫做变量。
关于赋值操作更多的详细内容请看第五章笔记
printf()函数
printf("I am a simple ");
printf("computer.\n");
printf("My favorite number is %d because it is first.\n", num);
首先,圆括号()
表明了这是一个函数,printf
是这个函数的名称,即函数的标识符。而圆括号中的内容是main()
函数传递给printf()
函数的信息,被称为函数参数。示例中的printf()
函数是C语言的一个标准函数,作用是格式化输出参数信息。
关于printf()
函数以及函数参数中的\n
、%d
等更多的信息请查看第四章笔记
return语句
在上面关于main()
函数介绍中,曾说”int
是main()
函数的返回类型,表明main()
函数返回的值是整数“。return
语句的作用便是返回相应的值。示例的最后一句return 0;
表示要返回数字0
。
C语言规定,有返回值的C函数必须要求return
语句,该语句以return
关键字开始,后面待返回的值。如果函数不需要返回任何值的话,则需要在对应位置使用void
关键字表明该函数不需要返回任何值。
进一步使用C
在看过第一个简单的C程序之后,再看一个更复杂的C程序
// fathm_ft.c -- 把2英寸转换为英尺
# include <stdio.h>
int main(void)
{
int feet, fathoms;
fathoms = 2;
feet = 6 * fathoms;
printf("There are %d feet in %d fathoms!\n", feet, fathoms);
printf("Yes, I said %d feet!\n", 6 * fathoms);
return 0;
}
结果如下:

解析
示例2-2比起示例2-1来说,变化不大,主要新增了
声明多个变量。声明多个变量时,变量与变量之间需要使用逗号隔开
int feet, fathoms;
乘法。示例2-2中使用了语句
feet = 6 * fathoms;
来执行乘法操作,主要意思是将变量fathoms
的值乘以6,然后将计算结果赋给变量feet
打印多个值。在第一条
printf()
语句中使用了两个替换符,替换符与变量一一对应,变量之间用逗号隔开;第二条printf()
语句说明待打印的值可以不是变量,只要是合适类型的变量即可
多个函数的C程序
上面的示例中我们都只编写了main()
函数,并在main()
函数中调用了的printf()
函数,但printf()
函数是C语言提供的。在示例2-3中我们将使用自己编写的函数,并在main()
函数中完成调用。
// two_func.c -- 一个文件中包含了两个函数
#include <stdio.h>
void butler(void); // C99标准的函数原型
int main(void)
{
printf("I will summon the butler function.\n");
butler(); // 函数调用
printf("Yes. Bring me some tea and writeable DVDs.\n");
return 0;
}
void butler(void) // 函数定义
{
printf("You rang, sir?\n");
}
运行结果如下:

解析
在示例2-3中,butler()
函数一共出现了三次。
函数原型,也可以称为函数声明,作用是告知编译器在程序中要使用该函数。在使用函数前,对函数进行声明是非常重要,就像变量一样,如果不进行声明,编译器在编译过程便会报错。同时,函数声明的形式也很重要,要以
返回类型 函数名称(函数参数);
形式,注意后面的分号不能忘记函数调用,示例中在
main()
函数中调用了butler()
函数函数定义,函数定义中便是函数本身的源代码
PS:何时执行函数取决于函数在main()
中被调用的位置,而不取决于函数定义的位置。即使将bulter()
函数定义写在main()
函数之前,也不会改变程序的执行顺序,仍然是上面的执行结果
关于函数的更多详细内容请查看第九章笔记
程序中的错误
在编写程序时,很容易就会犯一些错误,程序中出现的错误被称为bugs,而找出并修正错误的过程就叫做debug
程序中出现的错误总结归为以下两类
语法错误,即不遵循C语言的语法规则。最常见的语法错误就是忘记写分号,C语言规定每条语句结尾都应该有分号,如果忘记写分号,编译器就会报错
逻辑错误,程序没有得到预期的结果,即程序中出现逻辑上的错误。比如:本来要计算a的3次方,但由于编写程序失误,计算成了a的4次方。这种情况下,程序的语法没有错误,编译器顺利编译运行,但运行后的结果出错
一般来说,编译器可以直接报出语法错误,但对于逻辑错误,编译器便没有办法了,这时候可以使用调试器debugger来协助发现逻辑错误。
笔者
第二章主要的目的是对C程序有一个简单的了解。
从这章中我学到了
C程序由一个或多个函数组成。函数是C程序的基本模块。每个C程序都有一个
main()
函数,程序从main()
函数开始执行C语句以分号表示结束
声明是C语言的一个重要特性。在变量和函数使用前,都要进行声明,主要作用是向编译器表明程序中要使用这个变量或函数了
学会了
printf()
函数;学习了int
关键字,表示整型变量,可以在printf()
函数中使用%d
输出
《C Primer Plus》- 第二章 C语言概述的更多相关文章
- C Primer Plus_第二章_C语言概述_复习题与编程练习
REVIEW 1.如何称呼C程序的基本模块? ans 它们被称为函数 2.什么是语法错误?给出一个英语例子和一个C语言例子 me C的语法错误是指把正确的C符号放在了错误的位置 likes codin ...
- 第二章 c语言概述
一.#include指令和头文件 1.#include C预处理指令,C编译器在编译前对源代码做一些准备工作 2.stdio.h标准输入输出头文件,提供了关于输入输出的信息供编译器使用 头文件包含了建 ...
- 第二章 C语言编程实践
上章回顾 宏定义特点和注意细节 条件编译特点和主要用处 文件包含的路径查询规则 C语言扩展宏定义的用法 第二章 第二章 C语言编程实践 C语言编程实践 预习检查 异或的运算符是什么 宏定义最主要的特点 ...
- 01 C语言程序设计--01 C语言基础--第1章 C语言概述&第2章 GCC和GDB
走进嵌入式开发的世界,企业级项目课程让你达到企业嵌入式应用开发要求.名师在线答疑,解决疑难.科学评测体系,系统评估学习.核心项目实........ 30 门课程 241小时12分钟 824 人学习 学 ...
- 第1章 Java语言概述--HelloWorld--环境搭建
SE学什么 第1章 Java语言概述 第2章 基本语法 第3章 数组 第4章 面向对象编程(上) 第5章 面向对象编程(中) 第6章 面向对象编程(下) 第7章 异常处理 第8章 枚举类&注解 ...
- C#语言————第二章 C#语言快速热身
第二章 C#语言快速热身 ***********一.选择结构**************** 1:if选择结构与java的if选择结构语法完全相同 2:switch选择结构 ①:常量表达式的值可 ...
- javaSE习题 第一章 JAVA语言概述
转眼就开学了,正式在学校学习SE部分,由于暑假放视频过了一遍,略感觉轻松,今天开始,博客将会记录我的课本习题,主要以文字和代码的形式展现,一是把SE基础加强一下,二是课本中有很多知识是视频中没有的,做 ...
- [编程笔记]第一章 C语言概述
//C语言学习笔记 第一讲 C语言概述 第二讲 基本编程知识 第三讲 运算符和表达式 第四讲 流程控制 第五讲 函数 第六讲 数组 第七讲 指针 第八讲 变量的作用域和存储方式 第九讲 拓展类型 第十 ...
- [HeadFirst-JSPServlet学习笔记][第二章:高层概述]
第二章:高层体系结构 容器 1 什么是容器? servelet没有main()方法.它们受控于另一个Java应用,这个Java应用称为容器(Container) Tomcat就是这样一个容器.Web服 ...
随机推荐
- android中的简单animation(二)push up,push left,cross fade,hyperspace
animation_2.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout x ...
- 007.Oracle数据库 , 使用%进行模糊查询
/*Oracle数据库查询日期在两者之间*/ SELECT PKID, OCCUR_DATE, ATA FROM LM_FAULT WHERE ( ( OCCUR_DATE >= to_date ...
- 十八、React react-router4.x中:实现路由模块化、以及嵌套路由父子组件传值
一.路由模块化(用字典定义路由,然后循环出来) 1.官方文档参考 [官方文档]https://reacttraining.com/react-router/web/guides/quick-start ...
- CentOS7安装Jenkins与配置
安装 将Jenkins存储库添加到yum repos,并从此安装Jenkins. sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenki ...
- P1037 在霍格沃茨找零钱
转跳点:
- HDU - 1166 敌兵布阵 (线段树---点修改)
题意: 1.Add i j,i和j为正整数,表示第i个营地增加j个人(j不超过30) 2.Sub i j ,i和j为正整数,表示第i个营地减少j个人(j不超过30); 3.Query i j ,i和j ...
- MSDN原版系统镜像ISO下载站
官网 网址1:http://www.imsdn.cn/ Windows 10 最新版本 1909 正式版 ISO 镜像下载 (微软 MSDN / VL 官方原版系统) 网址2:https://www. ...
- NOIP2016天天爱跑步解题思路
算法:LCA,树上差分+(乱搞) 如果有写错的地方请大佬更正 对于100%数据: u表示起点,v表示终点 对于一条u到v的路径,先讨论LCA!=u&&LCA!=v的情况: 分为u到LC ...
- jquery快速常用技能
jQuery入口函数与js入口函数 (window.onload = function(){})的对比: 1.JavaScript的入口函数要等到页面中所有资源(包括图片.文件)加载完成才开始执行. ...
- Mysql 存储过程造测试数据
1.Mysql 存储过程造测试数据 -- 创建一个用户表 CREATE TABLE `sys_user` ( -- `id` CHAR (32) NOT NULL DEFAULT '' COMMENT ...