《C Primer Plus(第6版)中文版》读书笔记(第2章,2.25~3.17,2023)
ZenJiCh

《C Primer Plus(第6版)中文版》读书笔记(第2章,2.25~3.17,2023)

注:以下内容为个人读书学习备忘记录,仅供参考

建议购买本书或者自行搜索下载浏览本书PDF,进一步学习理解

解释:因为将博客框架从Gridea迁移到Hexo,花费些许时间,折腾了图床许久,所以第2章的学习时段相对比第1章要长些

摘录

第2章 C语言概述

典型的C程序

#include——预处理器指令

int main(void)——main()总是第一个被调用的函数——组成函数的语句

function a()——语句

function b()——语句

函数是C程序的构造块

根据C11标准,C语言有6种语句

C语言中的6种语句:1.标号语句

2.复合语句

3.表达式语句

4.选择语句

5.迭代语句

6.跳转语句

C语言的6种语句中都有的四个东西:关键字,标识符,运算符,数据

2.2.1 程序细节

1.#include指令和头文件
#include<stdio.h>——该行告诉编译器把stdio.h中的内容包含在当前程序中。
#include<stdio.h>的作用相当于把stdio.h文件中的所有内容都输入该行所在的位置。
实际上,这是一种“拷贝—粘贴”的操作。
#include这行代码是一条C预处理器指令(preprocessor directive)。
#include中的#符号表明,C预处理器在编译器接手之前处理这条指令。
通常,C编译器在编译前会对源代码做一些准备工作,即预处理(preprocessing)。
所有的C编译器软件包都提供stdio.h文件。
stdio.h是C编译器软件包的标准部分,它提供键盘输入和屏幕输出的支持。
该文件中包含了供编译器使用的输入和输出函数(如,printf())信息。
该文件名的含义是标准输入/输出头文件。
通常,在C程序顶部的信息集合被称为头文件(header)。
头文件大概指的就是.h扩展名的文件
头文件中可以定义一些常量,或者指明函数名以及如何使用它们。
但是,函数的实际代码在一个预编译代码的库文件中。
ANSI/ISO C规定了C编译器必须提供哪些头文件。
按照程序需求来使用头文件,省略必要的头文件可能不会影响某一特定程序,但是最好不要这样做。
本书每次用到库函数,都会用#include指令包含ANSI/ISO标准指定的头文件。
2.main()函数
函数是C程序的基本模块。
C程序一定从main()函数开始执行(目前不必考虑例外的情况)。
除了main()函数,你可以任意命名其他函数。
圆括号表明main()是一个函数名。
int和void是标准ANSI C定义main()的一部分
(如果使用ANSI C之前的编译器,请省略void;考虑到兼容的问题,请尽量使用较新的C编译器)
int是main()函数的返回类型。
int表明main()函数返回一个整数。
返回到这里?返回给操作系统。
void表明main()不带任何参数。
通常,函数名后面的圆括号中包含一些传入函数的信息。该例中没有传递任何信息。因此,圆括号内是单词void。

需要强调的是,只要坚持使用标准形式,把程序从一个编译器移至另一个编译器时就不会出什么问题。

3.注释
在程序中,被/* */两个符号括起来的部分是注释。写注释能让他人(包括自己)更容易明白你所写的程序。
C语言注释的好处之一是,可将注释放在任意的地方,甚至是与要解释的内容在同一行。
较长的注释可单独放一行或多行。
C99新增了另一种风格的注释,普遍用于C++和Java。这种新风格使用//符号创建注释,仅限于单行。
因为一行末尾就标志着注释的结束,所以这种风格的注释只需在注释开始处标明//符号即可。
一些编译器可能不支持这一特性。还有一些编译器需要更改设置,才能支持C99或C11的特性。
注意,注释只是为了帮助读者理解程序,编译器会忽略它们。
4.花括号,函数体和块
一般而言,所有的C函数都使用花括号标记函数体的开始和结束。这是规定,不能省略。
只能花括号({})能起这种作用,圆括号(())和方括号([])都不行。
左花括号({)表示函数定义开始,右花括号(})表示函数定义结束。
花括号还可用于把函数中的多条语句合并为一个单元或块。
5.声明
int num;
上面这行代码叫作声明(declaration)。声明是C语言最重要的特性之一。
在该例中,声明完成了两件事。
其一,在函数中有一个名为num的变量(variable)。
其二,int表明num是一个整数(即,没有小数点或小数部分的数)。
编译器使用这些信息为num变量在内存中分配存储空间。
分号在C语言中是大部分语句和声明的一部分,不像在Pascal中只是语句间的分隔符。
int是C语言的一个关键字(keyword)。
关键字是语言定义的单词,不能做其他用途。例如,不能用int作为函数名和变量名。
示例中的num是一个标识符(identifier),也就一个变量,函数或其他实体的名称。
因此,声明把特定标识符与计算机内存中的特定位置联系起来,同时也确定了储存在某位置的信息类型或数据类型。
在C语言中,所有变量都必须先声明才能使用。这意味着必须列出程序中用到的所有变量名及其类型。
C99和C11遵循C++的惯例,可以把声明放在块中的任何位置。
尽管如此,首次使用变量之前一定要先声明它。
声明变量的4个理由
1.如果事先未声明变量,C程序将无法通过编译。
2.把所有的变量放在一处,方便读者查找和理解程序的用途。如果变量名无法表述清楚,在注释中解释变量的含义。
3.声明变量会促使你在编写程序之前做一些计划。程序在开始时要获取哪些信息?希望程序如何输出?表示数据最好的方式是什么?
4.声明变量有助于发现隐藏在程序中的小错误,如变量名拼写错误。

注:给变量命名时要使用有意义的变量名或标识符。

如果变量名无法清楚地表达自身的用途,可在注释中进一步说明。

C99和C11允许使用更长的标识符名,但是编译器只识别前63个字符。

对于外部标识符(参阅第12章),只允许使用31个字符。

可以用小写字母,大写字母,数字,和下划线(_)来命名。

名称的第1个字符必须是字符或下划线,不能是数字。

操作系统和C库经常使用以一个或两个下划线字符开始的标识符(如,_kcab),因此最好避免在自己的程序中使用这种名称。

C语言的名称区分大小写,即把一个字母的大写和小写视为两个不同的字符。

6.赋值
num = 1;
赋值是C语言的基本操作之一。
该行代码的意思是“把值1赋给变量num”。
“=”是赋值运算符。
C语言通过赋值运算符(=)完成赋值操作。
在执行int num;声明时,编译器在计算机内存中为变量num预留了空间,然后在执行这行代码时,把值储存在之前预留的位置。
可以给num赋不同的值,这就是num之所以被称为变量(variable)的原因。
注意,该行代码从右侧把值赋到左侧。另外,该行代码以分号结尾。
7.printf()函数
printf("My favorite number is %d because it is first.\n",num);
在程序中使用函数叫作调用函数。
printf()函数是C语言的一个标准函数。
圆括号表明printf是一个函数名。
圆括号中的内容是从main()函数传递给printf()函数的信息。
该信息被称为参数,函数的实际参数(actual argument
在C语言中,实际参数(简称实参)是传递给函数的特定值,形式参数(简称形参)是函数中用于储存值的变量。
printf()函数用参数来做什么?
该函数会查看双引号中的内容,并将其打印在屏幕上。
\n组合(依次输入这两个字符)代表一个换行符(newline character)。
对于printf()而言,它的意思是“在下一行的最左边开始新的一行”。
换行符仅会影响程序输出的显示格式。
换行符是一个转义序列(escape sequence)。
转义序列用于代表难以表示或无法输入的字符。如,\t代表Tab键,\b代表Backspace键(退格键)。
每个转义序列都以反斜杠字符(\)开始。
%d相当于是一个占位符,其作用是指明输出num值的位置。
%提醒程序,要在该处打印一个变量,d表明把变量作为十进制整数打印。
printf()函数名中的f提醒用户,这是一种格式化打印函数。
8.return 语句
return 0;
int main(void)中的int表明main()函数应返回一个整数。C标准要求main()这样做。
该语句以return关键字开始,后面是待返回的值,并以分号结尾。
有返回值的C函数要有return语句。
因此,强烈建议读者养成在main()函数中保留return语句的好习惯。
注:在C语言中,return语句是一种跳转语句。

2.2.2 简单程序的结构

程序由一个或多个函数组成,必须有main()函数。
函数由函数头和函数体组成。
函数头包括函数名,传入该函数的信息类型和函数的返回类型。
通过函数名后的圆括号可识别出函数,圆括号里可能为空,可能有参数。
函数体被花括号括起来,由一系列语句,声明组成。
简而言之,一个简单的C程序的格式如下:
1
2
3
4
5
6
7
#include <stdio.h>
int main(void)
{
语句
return 0;
}
(大部分语句都以分号结尾。)

2.2.3 提高程序的可读性的技巧

编写可读性高的程序是良好的编程习惯。可读性高的程序更容易理解,以后也更容易修改和更正。提高程序的可读性还有助于你理清编程思路。以下并非是C语言的要求
1.选择有意义的函数名和写注释。
注意,使用这两种技巧时应相得益彰,避免重复啰嗦。
2.在函数中用空行分隔概念上的多个部分。
3.每条语句各占一行。

2.2.4 定义并使用自己的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

void butler<void>; /* ANSI/ISO C函数原型 */

int main(void)
{
butler();
return 0;
}


void butler(void) /* 函数定义开始 */
{
printf("Are you ready?\n");
}
butler()函数在程序中出现了3次。
第1次是函数原型(prototype),告知编译器在程序中要使用该函数;
第2次以函数调用(function call)的形式出现在main()中;
第3次出现在函数定义(function definition)中,函数定义即是函数本身的源代码。
函数原型是一种声明形式,告知编译器正在使用某函数,因此函数原型也被称为函数声明(function declaration)。
函数原型指明了函数的属性。
例如,butler()函数原型中的第1个void表明,butler()函数没有返回值(通常,被调函数会向主调函数返回一个值,但是butler()函数没有)
第2个void(butler(void)中的void)的意思是butler()函数不带参数。
注意,void在这里的意思是“空的”,而不是“无效”。
在main()中调用butler()很简单,写出函数名和圆括号即可。
程序的最后部分是butler()函数的定义,其形式和main()相同,都包含函数头和用花括号括起来的函数体。
函数头重述了函数原型的信息:butler()不带任何参数,且没有返回值。如果使用老式编译器,请去掉圆括号中的void。
何时执行butler()函数取决于它在main()中被调用的位置,而不是butler()的定义在文件中的位置。
记住,无论main()在程序文件处于什么位置,所有的C程序都从main()开始执行。
但是,C的惯例是把main()放在开头,因为它提供了程序的基本框架。

C标准建议,要为程序中用到的所有函数提供函数原型。标准include文件(包含文件)为标准库函数提供函数原型。

2.2.5 调试程序

程序的错误通常叫做bug,找出并修正错误的过程叫做调试(debug)。
2.2.5.1 语法错误
如果不遵循C语言的规则就会犯语法错误。
要理解该句子存在语法错误,需要具备基本的英文语法知识。
C语言的语法错误指的是,把有效的C符号放在错误的地方。
如何发现程序的语法错误?
首先,在编译之前,浏览源代码看是否能发现一些明显的错误。
接下来,查看编译器是否发现错误,检查程序的语法错误是它的工作之一。
在编译程序时,编译器发现错误会报告错误信息,指出每一处错误的性质和具体位置。
如果编译器报错某行缺少分号,请检查上一行。
2.2.5.2 语义错误
语义错误时指意思上的错误。
编译器无法检测语义错误,因为这类错误并未违反C语言的规则。
编译器无法了解你的真正意图,所以你只能自己找出这些错误。
如何发现程序的语义错误?
1.对于简单的程序来说,把自己想象成计算机,尽量忠实代码来模拟,跟着程序的步骤一步一步地执行
2.在程序中的关键点插入额外的printf()语句,以监视制定变量值的变化
通过查看值的变化可以了解程序的执行情况。
对程序的执行满意后,便可删除额外的printf()语句,然后重新编译。
3.使用调试器
调试器(debugger)是一种程序,让你一步一步运行另一个程序,并检查该程序变量的值。

2.2.6 关键字和保留标识符

关键字是C语言的词汇。它们对C而言比较特殊,不能用它们作为标识符(如,变量名)。
如果使用关键字不当(如,用关键字作为变量名),编译器会将其视为语法错误。
还有一些保留标识符(reserved identifier),C语言已经指定了它们的用途或保留它们的使用权。
如果你使用这些标识符来表示其他意思会导致一些问题。
因此,尽管它们也是有效的名称,不会引起语法错误,也不能随便使用。
保留标识符包括那些以下划线字符开头的标识符和标准库函数名,如printf()。

2.2.2 关键概念

程序员要具备抽象和逻辑的思维,并谨慎地处理细节问题(编译器会强迫你注意细节问题)。
作为程序员的任务是,在符合C标准的编译器框架中,表达你希望程序应该如何完成任务的想法。

本章小结

每个C程序必须包含一个main()函数,这是C程序要调用的第1个函数。

简单的函数由函数头和后面的一对花括号组成,花括号中是由声明,语句组成的函数体。

在C语言中,大部分语句都以分号结尾。

printf()函数用于输出想要表达的内容和变量的值。

语句的语义是语句要表达的意思。

编译器可以检测出语法错误,但是程序里的语义错误只有在编译完之后才能从程序的行为中表现出来。

检查程序是否有语义错误要跟踪程序的状态,即程序每执行一步后所有变量的值。

关键字是C语言的词汇。

心得

程序员要认真仔细地编写程序,注意程序运行的每一个细节。

告示:第3章的读书笔记的编写议程已经暂时取消了。

 评论