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

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

书名:C Primer Plus (第6版) 中文版

简介

作者:(美)普拉达(Prata,S.)

译者:姜佑

出版社:人民邮电出版社(北京),2016.4(2016.6重印)

摘录

第1章 初识C语言

1.2 选择C语言的理由

1.2.1 设计特性:C语言融合了计算机科学理论和实践的控制特性。
C语言的设计理念让用户能轻松地完成自顶向下的规划,结构化编程和模块化设计。
因此,用C语言编写的程序更易懂,更可靠。
1.2.2 高效性:实际上,C语言具有通常是汇编语言才具有的微调控制能力,可以根据具体情况微调程序以获得最 大运行速度或最有效地使用内存。
注:1.汇编语言是为特殊的中央处理单元设计的一系列内部指令,使用助记符来表示。
2.不同的CPU系列使用不同的汇编语言。
3.警惕内存泄漏问题
1.2.3 可移植性:这意味着,在一个系统中编写的C程序稍作修改或不修改就能其他系统运行。
但是要注意,程序中针对特殊硬件设备(如,显示监视器)或操作系统特殊功能
(如,Windows 10 或 Mac OS X)编写的部分,通常是不可移植的。
1.2.4 强大而灵活:(强大)C程序可以用于解决物理学和工程学的问题,甚至可用于制作电影的动画特效。
程序员利用C可以访问硬件,操控内存中的位。
(灵活)C语言有丰富的运算符,能让程序员简洁地表达自己的意图。
注:C没有Pascal严谨,但是却C++的限制多。
警告:许多任务用C语言来处理都非常简洁(如,转换数据的格式),但是你可能会犯一些莫名其妙的错误。
特别是,C语言使用指针,而涉及指针的编程错误往往难以察觉。
这些错误不可能在其他语言中出现。
C语言紧凑简洁,结合了大量的运算符。正因如此,我们也可以编写出让人极其费解的代码。
提醒:1.C语言在提供更多自由的同时,也让使用者承担了更大的责任。
2.因为我们有可能编写出让人难以理解的代码,所以我们需要人为定义代码编写规格形式,并且以此为基础形成代码编写规范
3.有句话说的好:想拥有自由就必须时刻保持警惕。

附:C++在C语言的基础上嫁接了面向对象编程工具。

注:1.面向对象编程是一门哲学,它通过对语言建模来适应问题,而不是对问题建模以适应语言。
2.C++几乎是C的超集,这意味着任何C程序差不多就是一个C++程序。

1.4 计算机能做什么

引子:在学习如何用C语言编程之前,最好先了解一下计算机的工作原理。
这些知识有助于你理解用C语言编写程序和运行C程序时所发生的事情之间有什么联系。
1.4.1 现代的计算机由以下多种部件构成。
1.中央处理单元(CPU,俗称为处理器或者中央处理器)承担绝大部分的运算工作,负责处理程序。
CPU由若干个寄存器组成,每个寄存器都可以储存一个数字。
2.随机存取内存(RAM,简称为内存)是存储程序和文件的工作区。
3.永久内存存储设备(过去一般指机械硬盘(HDD),现在还包括固态硬盘(SSD))即使在关闭计算机后,也不会丢失之前储存的程序和文件。
4.各种外围设备(如,键盘,鼠标,触摸屏,监视器)提供人与计算机之间的交互。
1.4.2 CPU的工作原理
简而言之,CPU从内存中获取并执行一条指令,然后再从内存中获取并执行下一条指令。
注:CPU能理解的指令有限并且具体(这些指令的集合叫作指令集)。
1.一个寄存器储存下一条指令的内存地址,CPU在内存里面找到这个地址,然后在这个地址里面获取和更新下一条指令。
2.在获取指令后,CPU在另一个寄存器中储存该指令,并更新第1个寄存器储存下一条指令的地址。
附:其一,储存在计算机中的所有内容都是数字。
计算机以数字形式储存数字和字符(如,在文本文档中使用的字母)。每个字符都有一个数字码。
计算机载入寄存器的指令也以数字形式储存,指令集中的每条指令都有一个数字码。
其二,计算机程序最终必须以数字指令码(即,机器语言)来表示。
1.4.3 计算机的工作原理
如果希望计算机做某些事,就必须为其提供特殊的指令列表(程序),确切地告诉计算机要做的事以及如何做。
你必须用计算机能直接明白的语言(机器语言)创建程序。
可是,用机器语言编程需要满足以下要求:
1.必须用数字码表示指令
2.要考虑CPU在完成任务时具体需要哪些步骤

1.5 高级编程语言和编译器

可是,用机器语言写成的指令(多条以数字码形式表现的指令),我们理解起来很费劲
为了简化编程工作,编写的指令易于理解,高级编程语言(如,C)应运而生
可是,计算机无法理解高级编程语言,因此编译器应运而生
编译器是把高级编程语言程序翻译成计算机能理解的机器语言指令集的程序。
可是,不同CPU制造商使用的指令系统和编码形式不同,也就是机器语言指令集不同。
但是,可以找到与特定类型CPU匹配的编译器。
因此,使用合适的编译器或编译器集,便可把一种高级编程语言程序转换成供各种不同类型CPU使用的机器语言程序。
简而言之,高级编程语言(如C,Java,Pascal)不受限于特定CPU或指令集。

1.6 语言标准

引子:在理想情况下,编写C程序时,假设该程序中未使用机器特定的编程技术,那么它的运行情况在任何实现中都应该相同。要在实践中做到这一点,不同的实现要遵循同一个标准。
1987年,布莱恩·柯林汉(Brian Kernighan)和丹尼斯·里奇(Dennis Ritchie)合著的The C Programming Language(《C语言程序设计》)第1版是公认的C标准,通常称之为K&R C或经典C
与大多数语言不同的是,C语言比其他语言更依赖库,因此需要一个标准库。
实际上,由于缺乏官方标准,UNIX实现提供的库已成为了标准库。
1.6.1 第1个 ANSI/ISO C标准
美国国家标准协会(ANSI)于1983年组建了一个委员会(X3J11),为C开发了一套新标准,并于1989年正式公布。
该标准(ANSI C)定义了C语言和C标准库。
国家标准化组织(ISO)于1990年采用了这套标准(ISO C)。
ISO C和ANSI C是完全相同的标准。
ANSI/ISO标准的最终版本通常叫做C89(因为ANSI于1989年批准该标准)或C90(因为ISO于1990年批准该标准)。
另外,由于ANSI先公布C标准,因此业界人士通常使用ANSI C。
注:在该委员会制定的指导原则中,最有趣的可能是:保持C的精神。
委员会在表述这一精神时列出了以下几点:
1.信任程序员;
2.不要妨碍程序员做需要做的事;
3.保持语言精练简单;
4.只提供一种方法执行一项操作;
5.让程序运行更快,即使不能保证其可移植性。
在最后一点上,标准委员会的用意是:作为实现,应该针对目标计算机来定义最合适的某特定操作,而不是强加一个抽象,统一的定义。在学习C语言过程中,许多方面都反映了这一哲学思想。
1.6.2 C99标准
1994年,ANSI/ISO联合委员会(C9X委员会)遵循了最初C90标准的原则开始修订C标准,最终发布了C99标准。
委员会的用意不是在C语言中添加新特性,而是为了达到新的目标。
第1个目标是,支持国际化编程。例如,提供多种方法处理国际字符集。
第2个目标是,“调整现有实现致力于解决明显的缺陷”。
因此,在遇到需要将C移至64位处理器时,委员会根据现实生活中处理问题的经验来添加标准。
第3个目标是,为适应科学和工程项目中的关键数值计算,提高C的适应性,让C比FORTRAN更有竞争力。
注:本书指出了许多C99修改的地方。
虽然该标准已发布了很长时间,但并非所有的编译器都完全实现C99的所有改动。
因此,你可能发现C99的一些改动在自己的系统中不可用,或者只有改变编译器的设置才可用。

1.6.3 C11标准

标准委员会在2011年发布了C11标准。
委员会提出了一些新的指导原则。出于对当前编程安全的担忧,不那么强调“信任程序员”目标了。
C99的一些特性成为C11的可选项。
C11标准添加了可选项支持当前使用多处理器的计算机。
注:对于C11标准,我们浅尝辄止,深入分析这部分内容已超出本书讨论的范围。

注意:

本书使用术语ANSI C,ISO C或ANSI/ISO C讲解C89/90和较新标准共有的特性,用C99或C11介绍新的特性,有时也使用C90(例如,讨论一个特性被首次加入C语言时)。

1.7 使用C语言的7个步骤

C是编译型语言。

注意,这是理想状态。在实际的使用过程中,尤其是在较大型的项目中,可能要做一些重复的工作,根据下一个步骤的情况来调整或改进上一个步骤。
1.7.1 第1步:定义程序的目标
在动手写程序之前,要在脑中有清晰的思路。想要程序去做什么首先自己要明确自己想做什么,思考你的程序需要哪些信息,要进行哪些计算和控制,以及程序应该要报告什么信息。
1.7.2 第2步:设计程序
对程序应该完成什么任务有概念性的认识后,就应该考虑如何用程序来完成它。
例如,用户界面应该是怎样的?如何组织程序?目标用户是谁?准备花多长时间来完成这个程序?
除此之外,还要决定在程序(还可能是辅助文件)中如何表示数据,以及用什么方法处理数据。
通常,选择一个合适的方式表示信息可以更容易地设计程序和处理数据。
1.7.3 第3步:编写代码
设计好程序后,就可以编写代码来实现它。
顾名思义,将你设计的程序翻译成C语言,并将其输入到你的电脑里面的代码编辑器(例如,Visual Studio Code)
在这一步骤中,应该给自己编写的程序添加文字注释。
最简单的方式是使用C的注释工具在源代码中加入对代码的解释。
通常,代码编辑器(例如,Visual Studio Code)本身或者扩展会集成C的注释工具,所以直接在代码编辑器加入对代码的解释即可
1.7.4 第4步:编译
顾名思义,用编译器编译你的代码编辑器那里的源代码
注意,编译的细节取决于编程的环境。
C编译器负责把C代码翻译成特定的机器语言。
此外,C编译器还将源代码与C库(库中包含大量的标准函数供用户使用,如printf()和scanf())的代码合并成最终的程序。
更精确地说,应该是由一个被称为链接器的程序来链接库函数,但是在大多数系统中,编译器运行链接器。
其结果是,生成一个用户可以运行的可执行文件,其中包含着计算机能理解的代码。
编译器还会检查C语言程序是否有效。如果C编译器发现错误,就不生成可执行文件并报错。
理解特定编译器报告的错误或警告信息是程序员要掌握的另一项技能。
1.7.5 第5步:运行程序
传统上,可执行文件是可运行的程序。
在常见环境(包括Windows命令提示符模式,UNIX终端模式和Linux终端模式)中运行程序要输入可执行文件的文件名,而其他环境可能要运行命令(如,在VAX中的VMS)或一些其他机制。
最终生成的程序可通过单击或者双击文件名或图标直接在操作系统中运行。
1.7.6 第6步:测试和调试程序
程序能运行是个好迹象,但有时也可能会出现运行错误。
程序中的错误,计算机行话叫作bug,查找并修复程序错误的过程叫调试。
不过,现在的编译器会捕获许多错误,而且自己也可以根据本书的一些调试的建议找到编译器未发现的错误。
1.7.7 第7步:维护和修改代码
创建完程序后,你发现程序有错,或者想扩展程序的用途,这时就要修改程序。
如果在编写程序时清楚地做了注释并采用了合理的设计方案,这些事情都很简单。
1.7.8 说明
编程并非像描述那样是一个线性的过程。有时,要在不同的步骤之间往复。
磨刀不误砍柴工,应该养成先规划再动手编写代码的好习惯,用纸和笔记录下程序的目标和设计框架。

1.8 编程机制

用C语言编写程序时,编写的内容被储存在文本文件中,该文件被称为源代码文件(source code file)。
大部分C系统,包括之前提到的,都要求文件名以.c结尾(如,wordcount.c和budget.c)。
在文件名中,点号(.)前面的部分称为基本名(basename),点号后面的部分称为扩展名(extension)。
因此,budget是基本名,c是扩展名。基本名与扩展名的组合(budget.c)就是文件名。
1.8.1 目标代码文件,可执行文件和库
C编程的基本策略是,用程序把源代码文件转换为可执行文件(其中包含可直接运行的机器语言代码)。
典型的C实现通过编译和链接两个步骤来完成这一过程。
编译器把源代码转换成中间代码,链接器把中间代码和其他代码合并,生成可执行文件。
C使用这种分而治之的方法方便对程序进行模块化,可以独立编译单独的模块,稍后再用链接器合并已编译的模块。
另外,链接器还将你编写的程序和预编译的库代码合并。

编译源代码的具体流程

1.把源代码转换为机器语言代码,并把结果放在目标代码文件(或简称目标文件)中(这里假设源代码只有一个文件)。
2.在目标代码文件中添加启动代码(startup code)。
注:启动代码充当着程序和操作系统之间的接口。
3.在目标代码文件中添加库函数的代码。几乎所有的C程序都要使用C标准库中的函数。
目标代码文件不包含库函数的代码,只包含了使用库函数的指令。
库函数真正的代码储存在另一个被称为库的文件中。库文件中有许多函数的目标代码。
链接器的作用是:把你编写的目标代码,系统的标准启动代码和库代码这3部分合并成一个文件,即可执行文件。
对于库代码,链接器只会把程序中要用到的库函数代码提取出来。
简而言之,目标文件和可执行文件都由机器语言指令组成的。
然而,目标文件中只包含编译器为你编写的代码翻译的机器语言代码,可执行文件还包含你编写的程序中使用的库函数和启动代码的机器代码。
注:C编译器会创建一个与源代码基本名相同的目标代码文件,可是,却找不到这个文件。
因为一旦链接器生成了完整的可执行程序,就会将其删除。
如果原始程序有多个源代码文件,则保留目标代码文件。
在有些系统中,必须分别运行编译程序和链接程序,而在另一些系统中,编译器会自动启动链接器,用户只需给出编译指令即可。
1.8.2 PC的命令行编译器
C编译器不是标准Windows软件包的一部分,因此需要从别处获取并安装C编译器(Cygwin和MinGW)
这样便可在PC上通过命令行使用GCC编译器。
Cygwin在自己的视窗运行,模仿Linux命令行环境,有一行命令提示。
MinGW在Windows的命令提示模式中运行。
源代码文件的扩展名应该是.c
通常,C编译器生成的中间目标代码文件的扩展名是.obj(也可能是其他扩展名)。
有些编译器生成带.asm扩展名的汇编语言文件,而有些编译器则使用自己特有的格式。
一些编译器在编译后会自动运行链接器,另一些要求用户手动运行链接器。
在可执行文件中链接的结果是,在原始的源代码基本名后面加上.exe扩展名。
1.8.3 集成开发环境(Windows)
引子:根据Statcounter数据图表,从2022年1月到2023年2月,Windows分别占据全球与中国桌面操作系统市场75.19%与85.38%的市场份额
以下为Statcounter相关的数据图表

image

image

因此,重点摘录Windows下的集成开发环境(IDE)
通常,Windows下的集成开发环境(IDE)既可处理C也可处理C++,因此要指定待处理的程序是C还是C++
注:大多数C程序也可以作为C++程序运行
众所周知,Windows下的集成开发环境(IDE),非Microsoft Visual Studio莫属
可是,对于新手来说,Microsoft Visual Studio太过臃肿,所以,推荐新手使用Visual Studio Code
注:Visual Studio Code是代码编辑器,不是集成开发环境(IDE)
所以,建议新手百度Visual Studio Code C语言开发环境配置,按照百度出来的教程配置Visual Studio Code

你可能会遇到一个问题:在程序执行完毕后,执行程序的窗口立即消失。

如果不希望出现这种情况,可以让程序暂停,直到你按下Enter键,窗口才消失。

要实现这种效果,可以在程序的最后(return这行代码之前)添加下面一行代码:

getchar();

该行读取一次键的按下,所以程序在用户按下Enter键之前会暂停。

有时根据程序的需要,可能还需要一个击键等待。

这种情况下,必须用两次getchar():

getchar();

getchar();

1.8.4 Windows/Linux
许多Linux发行版都可以安装在Windows系统中,以创建双系统。
一些存储器会为Linux系统预留空间,以便可以启动Windows或Linux。
不能通过Windows系统访问Linux文件,但是可以通过Linux系统访问Windows文档。

本章小结

C是强大而简洁的编程语言。

它之所以流行,在于自身提供大量的实用编程工具,能很好地控制硬件。

而且,与大多数其他程序相比,C程序更容易从一个系统移植到另一个系统。

C是编译型语言。

C编译器和链接器是把C语言源代码转换成可执行代码的程序。

心得

编写C程序之前强烈建议程序的思路在脑子里过一遍,然后在纸上写一下程序具体执行的步骤,或者在电脑上画个程序运行的流程图,最后才在代码编辑器或者集成开发环境(IDE)编写C程序。

 评论