《C Primer Plus》第一章——笔记、复习题及编程练习

文章目录

初始C语言

C语言的优点

  1. 设计特性:C融合了计算机科学理论和实践的控制特性,能够让用户轻松地完成自顶向下的规划、结构化编程、模块化设计
  2. 高效性:C语言程序相对更紧凑,而且运行速度很快。可以根据具体情况微调程序以获得最大运行速度或最有效的使用内存
  3. 可移植性:在一种系统中编写的C语言稍作修改或不修改就能在其他系统运行。但是注意,程序中针对特殊硬件设备或操作系统的特殊功能编写的部分,通常是不可移植的。
  4. 强大且灵活
  5. 面向程序员:许多任务用C来处理都非常简洁,可以利用C访问硬件、操控内存中的位。缺点是可能会犯一些莫名其妙的错误,这些错误不可能在其他语言中出现,C语言在提供更多*的同时,也让使用者承担了更大的责任。

基础计算机知识

现代计算机由多种部件组成:

*处理单元(CPU)承担绝大部分的运算工作。随机存取内存(RAM)是存储程序和文件的工作区,而永久内存存储设备(机械硬盘和固态硬盘)即使在关闭计算机后也不会丢失数据。

CPU的工作原理:

从内存中获取并执行一条指令,然后再从内存中获取并执行下一条指令。CPU有若干个寄存器组成,每个寄存器都可以存储一个数字。一个寄存器存储下一条指令的内存地址,CPU使用该地址去获取和更新下一条指令,获取指令后,CPU早另一个寄存器内存储该指令,并更新第一个寄存器存储下一条指令的地址。CPU理解的指令有限(指令的集合叫做指令集),而且指令相当具体,比如把一个数字从内存移动到寄存器。

计算机内部所有数据,包括数字、文本、指令等都是由二进制编码存储的,所以计算机只能识别机器语言(二进制编码)。比如要实现两数相加的操作:

  1. 从内存位置2000上把第一个数字拷贝到寄存器1
  2. 从内存位置2004上把另一个数字拷贝到寄存器2
  3. 把寄存器2的内容与寄存器1中的内容相加,结果存储在寄存器1中
  4. 把寄存器1中的内容拷贝到内存位置2008

了解一些汇编语言知识,便可深刻理解该部分内容

高级计算机语言和编译器

编译器把高级语言程序翻译成计算机能理解的机器语言指令集的程序。

高级语言以更抽象的方式描述行为,不受限于特定CPU或指令集。一般来说,不同CPU制造商使用的指令系统和编码格式不同,所以为特定型号CPU编写的机器语言程序不能被其他CPU理解,但是可以找到特定类型CPU匹配的编译器,便可把一种高级语言程序转换为各种不同类型CPU的使用的机器语言程序。

语言标准

第一个 ANSI/ISO C标准

美国国家标准协会(ANSI)与1983组建一个委员会并开发一套新标准,定义了C语言和C标准库。国际标准化组织于1990年采用了这套标准(ISO C)。ISO C与ANSI C是完全相同的标准。这套标准通常称为C90或C89。

委员会制定的指导原则中包含:保持C的精神,委员会表述这一精神时列出了以下几点:

  1. 信任程序员
  2. 保持语言精练简单
  3. 只提供一种方法执行一项操作
  4. 让程序运行更快,即使不能保证可移植性

在最后一点上,标准化委员会的用意是:作为实现,应该针对目标计算机来定义最合适的某种特定操作,而不是强加一个抽象、统一的定义。

C99标准

委员会用意并不是增加新特性,而是为了达到新目标。第一个目标是:支持国际化编程,如:提供多种方法处理国际字符集。第二个目标是:调整现有实践致力于解决明显的缺陷。第三个目标是,为了适应科学和工程项目中的关键数值计算,提高C的适应性。

C11标准

出于对当前编程安全的担忧,不再那么强调相信程序员。

供应商并未像支持C90一样很好的支持C99,使得一些C99特性变为C11的可选项。因为委员会认为不应该要求小型机市场的供应商支持其目标环境中用不到的特性。

修订新标准并不是意味着原标准不能用,而是为了跟进新的技术。

使用C语言的7个步骤

  1. 定义程序目标:动手写程序之前要有清晰的思路,想要程序去做什么首先自己要明确自己想做什么。思考程序需要的信息,进行哪些计算和控制,程序需要报告哪些信息。这一步骤不涉及具体的计算机语言,应该用一般术语来描述问题。
  2. 设计程序:考虑如何用程序来完成它。如界面是怎么样的,如何组织程序,目标用户,计划时间。除此之外还要决定在程序中如何表示数据,如何处理数据。学习之初问题很简单,不需要选择,但是随着处理情况越来越复杂,需要考虑的方面也越多,通常选择一个合适的方式表示信息可以更容易的设计程序和处理数据。
  3. 编写代码:使用具体的编程语言实现思路。在编写过程中添加文字注释。
  4. 编译:C编译器负责把C代码翻译成特定的机器语言。此外,C编译器还将源代码与C库的代码合并成最终的程序(更精确地说,应该是由一个被称为链接器的程序来链接库函数,但是在大多数系统中,编译器运行链接器)。其结果是,生成一个用户可以运行的可执行文件,其中包含着计算机能理解的代码。编译器还会检查C语言程序是否有效。如果C编译器发现错误,就不生成可执行文件并报错。理解特定编译器报告的错误或警告信息是程序员要掌握的另一项技能。
  5. 运行程序:不同系统的运行方式有所不同
  6. 测试与调试程序:查找并修复程序错误的过程叫调试。
  7. 维护和修改代码:创建程序后发现程序有错,或想拓展程序的用途,这时就要修改程序。

编程并不是上述的线性过程,有时需要在不同步骤之间往复。许多初学者经常忽略第一二步,直接开始编写代码,初学时因为程序简单,完全可以在脑中构思好整个过程,但是随着程序越来越庞大复杂,则这种方法就不可行了。最终那些跳过前两步的人往往浪费了更多的时间,因为他们写的程序难看,缺乏条理,让人难以理解。

编程机制

用C语言编写程序时,编写的内容被存储在文本文件中,该文件被称为源代码文件(source code file)。大部分C系统,包括之前提到的,都要求文件名以.c结尾。在文件名中,点号(.)前面的部分称为基本名(basename),点号后面的部分称为扩展名(extension)。基本名与扩展名的组合就是文件名。

目标代码文件、可执行文件和库

C编程的基本策略是,用程序把源代码文件转换为可执行文件(其中包含可直接运行的机器语言代码)。

典型的C实现通过编译和链接两个步骤来完成这一过程。编译器把源代码转换成中间代码,链接器把中间代码和其他代码合并,生成可执行文件。C使用这种分而治之的方法方便对程序进行模块化,可以独立编译单独的模块,稍后再用链接器合并已编译的模块。通过这种方式,如果只更改某个模块,不必因此重新编译其他模块。

另外,链接器还将你编写的程序和预编译的库代码合并。

中间文件有多种形式。我们在这里描述的是最普遍的一种形式,即把源代码转换为机器语言代码,并把结果放在目标代码文件中。虽然目标文件中包含机器语言代码,但是并不能直接运行该文件。因为目标文件中存储的是编译器翻译的源代码,这还不是一个完整的程序。

目标代码文件缺失启动代码(startup code)。启动代码充当着程序和操作系统之间的接口。

目标代码还缺少库函数。几乎所有的C程序都要使用C标准库中的函数。

链接器的作用是,把你编写的目标代码、系统的标准启动代码和库代码这3部分合并成一个文件,即可执行文件。对于库代码,链接器只会把程序中要用到的库函数代码提取出来。

简而言之,目标文件和可执行文件都由机器语言指令组成的。然而,目标文件中只包含编译器为你编写的代码翻译的机器语言代码,可执行文件中还包含你编写的程序中使用的库函数和启动代码的机器代码。

《C Primer Plus》第一章——笔记、复习题及编程练习

GNU编译器集合和LLVM项目

GNU项目始于1987年,是一个开发大量*UNIX软件的集合。GNU编译器集合(也被称为GCC,其中包含GCC C编译器)是该项目的产品之一。GCC在一个指导委员会的带领下,持续不断地开发,它的C编译器紧跟C标准的改动。GCC有各种版本以适应不同的硬件平台和操作系统,包括UNIX、Linux和Windows。用gcc命令便可调用GCC C编译器。许多使用gcc的系统都用cc作为gcc的别名。

LLVM项目成为cc的另一个替代品。该项目是与编译器相关的开源软件集合,始于伊利诺伊大学2000年的研究项目。它的Clang编译器处理C代码,可以通过clang调用。有多种版本供不同的平台使用,包括Linux。2012年,Clang成为FreeBSD的默认C编译器。Clang也对最新的C标准支持得很好。

不同系统的编译方式

请查阅手册或其他资料,这里不再记录。

本章小结

C是强大而简洁的编程语言。它之所以流行,在于自身提供大量的实用编程工具,能很好地控制硬件。而且,与大多数其他程序相比,C程序更容易从一个系统移植到另一个系统。

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

用C语言编程可能费力、困难,让你感到沮丧,但是它也可以激发你的兴趣,让你兴奋、满意。我们希望你在愉快的学习过程中爱上C。

复习题

  1. 对编程而言,可移植性意味着什么?
  2. 解释源代码文件、目标代码文件和可执行文件有什么区别?
  3. 编程的7个主要步骤是什么?
  4. 编译器的任务是什么?
  5. 链接器的任务是什么?

  1. 完美的可移植程序是,其源代码无需修改就能在不同计算机系统中成功编译的程序。
  2. 源代码文件包含程序员使用的任何编程语言编写的代码。目标代码文件包含机器语言代码,它不必是完整的程序代码。可执行文件包含组成可执行程序的完整机器语言代码。
  3. (1)定义程序目标;(2)设计程序;(3)编写程序;(4)编译程序;(5)运行程序;(6)测试和调试程序;(7)维护和修改程序。
  4. 编译器把源代码(如,用C语言编写的代码)翻译成等价的机器语言代码(也叫作目标代码)。
  5. 链接器把编译器翻译好的源代码以及库代码和启动代码组合起来,生成一个可执行程序。

编程练习

我们尚未要求你编写C代码,该练习侧重于编程过程的早期步骤。

你刚被公司聘用。该公司准备进入欧洲市场,需要一个把英寸单位转换为厘米单位(1英寸=2.54厘米)的程序。该程序要提示用户输入英寸值。你的任务是定义程序目标和设计程序(编程过程的第1步和第2步)。

问题分析:

定义程序目标:该程序的目标是转换单位,将英寸转换为厘米,转换关系为1英寸 = 2.54厘米。

程序在开始输出提示信息:请输入英寸单位的数值,该程序将自动为您转换为cm。

需要用户输入数值

反馈转换后的cm值

界面为控制台界面。

// 取消Microsoft Visual Studio的scanf等函数的安全警告错误
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main(void) {
	float inch;
	printf("请输入英寸单位的数值,该程序将自动为您转换为cm:\n");
	scanf("%f", &inch);
	printf("转换后的厘米值为:%f\n", inch*2.54);
	return 0;
}

程序改进:可以多次输入与转换,可以实现厘米与英寸的互相转换 判断输入的字符串是否是数字

待改进:judge输入错误处理,num输入非法数字。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<string.h>
int main(void) {
	// 声明两个变量:分别用来存取用户输入的转换数值与判断选项
	float num;
	int judge;
	// 进行一个循环,不断的输出提示信息,输入并转换
	while (true) {
		// 输出提示信息
		printf("------------------------\n请问您将要进行的操作为:\n1. 英寸单位==>厘米单位\n2.厘米单位==>英寸单位\n3.退出程序\n------------------------\n");
		// 输入选项
		scanf("%d", &judge);
		// 进如选项判断分支语句
		switch (judge)
		{
		case 1:
			// 提示信息
			printf("请输入以英寸为单位的数值:\n");
			// 输入数字至num变量
			scanf("%f", &num);
			// 进行转换输出
			printf("其对应的以厘米为单位的数值为:%f\n", num*2.54);
			break;
		case 2 :
			printf("请输入以厘米为单位的数值:\n");
			scanf("%f", &num);
			printf("其对应的以厘米为单位的数值为:%f\n", num/2.54);
			break;
		case 3:
			printf("程序结束!");
			// 输出提示信息,退出程序
			return 0;
			break;
		default:
			// 不是选项值,输出错误信息
			printf("输入选项错误,请重新输入;\n");
			// 进入下一轮循环
			continue;
			break;
		}
	}
	return 0;
}
上一篇:读书笔记1: 《C++ Primer》中文版 第5版


下一篇:C++Primer(第五版 )第二章 变量和基本类型 章节编程练习答案