读《The C Programming Language》(7)

限时加码!20+主流AI编程工具免费用 购周边加赠Coding Plan Lite,Claude Code、Cursor等即刻畅享,学习进阶更高效! 阅读详情

第五章讲的是指针和数组。指针是C语言的精华,但同时也是最难和最容易混淆的地方。读这一章真是如履薄冰,小心翼翼。从第一节到第十二节,难度依次增大,如果前面放过了一些不清楚的地方,到后面看到char (*(*x[3])())[5]这样的东西就只有哭的力气了。

本章一开始作者就告诉了你指针是什么,"A pointer is a variable that contains the address of a variable."这里面有三层意思:1.指针是一个变量;2.这个变量的内容是一个地址;3.这个地址是内存中变量的地址。理解了指针是内存中变量的地址,也就理解了指针的本质。

第一节 指针和地址

这一节在提到一元运算符&时提到,&只能被应用于内存中的对象,也就是变量和数组元素,而不能用在表达式、常量和寄存器变量。所以如果想把一个常数作为参数传给一个要求指针的函数,必须把这个常数赋给一个变量,然后把这个变量的地址传给函数。例如,int i = 8, j = 9; swap(&i, &j);

另外,作者在提到指针的声明时,说其实变量、表达式、函数的声明都是一致的。比如double d, *dp, atof(char *); *dp可以看成是一个表达式,它是一个double型的。以前我们写程序时,对指针会有两种写法,char* c和char *c,作者这么一说我明显觉得后者更合理了。

第二节 指针和函数参数

这一节提到因为C语言的函数调用是传值的,所以不可能改变调用函数的变量,改变的只是这些变量的一份拷贝。如果想改变,可以传指针过去,通过地址访问和改变调用函数的变量。作者同时提到,如果一个函数想返回两个或多个值,也可以通过传进来的指针记录这样的值,库函数scanf就是这么干的。

第三节 指针和数组

相信很多人对指针的糊涂就是从指针和数组的关系开始的。作者在这一节特别强调了指针和数组的密切关系,"Any operation that can be achieved by array subscripting can also be done with pointers." 任何用数组下标可以完成的操作都可以通过指针完成,而且指针的效率更高。实际上,C在计算数组元素a[i]时,会把它转化成*(a+i)。这两种形式是完全等价的。

另外,C函数的参数传递是传值的,这一点在参数是指针时仍然成立。被调用函数获得的参数指针实际上是调用函数中的指针的拷贝。比如一个函数调用function(a),其中a是一个数组名,那么传给函数function的参数实际上是a数组的首地址的拷贝。这使得函数function可以对传入的参数作诸如a++之类的操作,因为这时的指针参数是一个局部变量,而不是原来的数组名。而对数组名作诸如a++之类的操作是非法的。以上所讲的和我们以前说的传指针可以改变调用函数的变量并不矛盾。虽然传指针也是按值传了一份拷贝,但这份拷贝所指向的仍然是调用函数中的变量,所以针对它的操作仍然可以改变这个变量。

最后,作者提到,给一个函数还可以传递数组的一部分作为参数,比如f(&a[2])或者f(a+2)。在这种情况下,如果被调用函数可以肯定传来的指针指向的是数组中间的某个元素,它甚至可以用负数作为下标去访问这个元素前面的元素,比如p[-1], p[-2]等!

第四节 地址算术

在这一节作者强调。"C is consistent and regular in its approach to address arithmetic; its integration of pointers, arrays, and address arithmetic is one of the strengths of the language." 这一点我深表赞同,指针、数组和地址算术统一起来不仅是C的优势,而且应该是C最强大的地方。接下来作者用了一个最简单的内存管理程序(分配和释放)说明了这种统一。

这个十几行的小程序说明了内存分配和释放的最基本原理:内存分配就是返回空闲区域的指针,同时把空闲区域的指针向前挪n(n是刚分配的区域大小)个位置;而回收只是简单的把空闲区域的指针回挪n(n是刚回收的区域大小)个位置。这个程序还展示了指向同一个数组的两个指针可以比较大小,大的减小的还可以得出它们之间相差了几个位置。这个位置的差距和数组元素的类型大小无关,C语言在计算指针位置时会自动考虑数组元素的类型。这就是作者所说的"All the pointer manipulations automatically take into account the size of the objects pointed to."。

第五节 字符指针和函数

本节一开始作者就告诉读者,字符串常量是一个字符数组,它的存储长度要比字符数多一个('/0')。在程序中访问字符串常量是通过指向第一个字符的指针。我们用printf("Hello, world")打印字符串时,也许没有注意到printf接受的参数其实是char *。作者特别提醒

char amessage[] = "now is the time";
char *pmessage = "now is the time";

这两者是有很大不同的。前者是对数组的初始化过程,无论数组元素怎么改变,amessage始终指向固定的第一个数组元素。后者是一个指针变量的初始化过程,使pmessage 指向字符串常量"now is the time"的第一个字符,而它有可能随后被重新赋值,指向不同存储位置的另一个字符串。

第六节 指针数组;指针的指针

对指针和数组有点糊涂的人到这里就更糊涂了。为了说明指针数组和指针的指针的用法,作者举了一个给若干字符串排序的例子。给数组的每一个元素填充一个指向一个字符串的指针,这大概是指针数组最常用的形式吧。在这个例子中,声明char *lineptr[MAXLINES]指出lineptr是一个长度为MAXLINES的数组,里面每一个元素是指向char型的指针。lineptr[i]是一个字符指针,而*lineptr[i]是这个指针指向的字符。将*lineptr++放在循环中就可以遍历一个个字符串。

第七节 多维数组

C中的二维数组时按行存储的,相当于一个一维数组,每一个数组元素是一个数组。值得注意的是,二维数组作为函数参数时,列是必须指定的,而行则无关紧要。比如f(int daytab[][13]) { ... },它相当于f(int (*daytab)[13]) { ... },其中daytab是指向长度为13的整形数组的指针。对于多维数组来说,只有第一维可以不指定,其它的必须指定。

第八节 指针数组的初始化

作者举了一个字符串数组的例子:

/* month_name: return name of n-th month */
char *month_name(int n)
{
    static char *name[] = {
        "Illegal month",
        "January", "February", "March",
        "April", "May", "June",
        "July", "August", "September",
        "October", "November", "December"
    };
    return (n < 1 || n > 12) ? name[0] : name[n];
}

在这个例子里,除了能看到字符指针数组的初始化,还能看到静态局部变量的妙用。这个数组不会随着函数的调用和返回而创建和销毁,而且只能为这个函数所用。另外,这个例子再一次体现了字符串常量在程序中通过它的首地址访问。字符串的首地址被赋给字符指针数组的元素。

第九节 指针vs.多维数组

 作者重点比较了二维数组和指针数组的区别。比如int a[10][20];和int *b[10];,区别有以下几点:1. 前者是一个二维数组,系统给它分配了200个整形变量的存储空间,而后者是一个指针数组,系统只分配给它10个指针的存储空间;2. 前者只能是矩形,而后者可以是锯齿形的,指针数组中的指针可以指向任何长度的数组。

第十节 命令行参数

本节作者提到了给main函数传递参数的方式,并且举例介绍了如何处理这些参数。这一节并没有对指针的性质或者用法做什么扩展,但举的几个例子有一定难度,看懂之后会觉得写得相当经典,特别是最后一个。

第十一节 函数指针

函数指针让程序有了更大的灵活性,可以把程序中的相对独立又容易改变的算法部分用函数指针代替,从而让这部分可以配置,有点类似面向对象中的策略模式。作者用一个排序的例子说明了函数指针的用法,但并没有展开讲。也许是因为在实际总应用的少吧,感觉这部分的讲述不是很丰满。

第十二节 复杂声明

这一节出现了把指针、数组和函数揉在一起的表达式,就像开篇举的那个例子一样。作者为了让大家能读懂这样的变态表达式,特地写了一个程序把这样的式子翻译成英语,比如开篇的那个char (*(*x[3])())[5]就翻译成x: array[3] of pointer to function returning pointer to array[5] of char。可是在我看来,别说原来的表达式,就是这个翻译出来的英文“短”语大概也会让很多人当场晕倒。这个程序的教学意义应该要比实际意义大。我在想,能不能写一个把这种变态表达式翻译成汉语的程序,这个程序应该要比英语的难得多。呵呵,不知道有没有人有兴趣一试。

The C programming language》学习笔记 Brian和Dennis的《c程序设计语言》(The C Programming Language)真不愧为c语言方面的经典书籍,薄薄的一本,却让人爱不释手,每次阅都能有所收获。好记忆不如烂笔头,有些规则、算法还是记录下来比较好,记录下来常常回顾,才是提升编程内功的不二法门。下面言归正传…… 阅读详情

相关推荐

【第一部分 第一章】The C Programming Language 程序研究 【持续更新】

The C Programming Language程序研究   前言 C语言之父创作的The C Programming Language一书对于所有学习C语言的人来说都可以算作一部圣经。它不到200页的篇幅却几近完整地阐述了C语言的各个方面,不仅如此,书中的每个例程和练习都展现了作者丰富的C编程经验,对于初学者来说这些例程和练习并不是那么简单,即使是对于有些经验的C语言工作者来说,也有很

DuanXu-yzc 2156

Java面向对象高级--继承的应用----整形数组类、排序类、反转类

分析: class Array{ // 表示数组 private int temp[] ; // 整型数组 private int foot ; // 定义添加位置 public Array(int len){ if(len>0){ this.temp = new int[len] ; }else{ this.temp = new int[1] ; //

吴英强的技术博客 2184

The C programming Language推荐

The C Programming Language译作《C程序设计语言》,是由著名的计算机科学家Brian W. Kernighan和C语言之父的Dennis M. Ritchie合著的一部计算机科学著作,是第一部介绍C语言编程方法的书籍。它是一本必的程序设计语言方面的参考书。它在C语言的发展和普及过程中起到了非常重要的作用,被视为是C语言的业界标准规范,而且至今仍然广泛使用。它也被公认为计算机

zz9629的博客 2431

c语言基础 2

<br />指针与数组(c语言):<br /> ANSI C使用类型void * (指向void的指针)代替char* 作为通用指针的类型。 <br /> 地址运算符&只能应用于内存中的对象,即变量与数组元素。它不能作用于表达式,常量或register类型的变量。<br /> 我们应该注意,指针只能指向某种特定类型的对象,也就是说,每个指针都必须指向某种特定的数据类型。一个<br /> 例外是指向void类型的指针可以存放指向任何类型的指针,但它不能间接引用其自身。<br /><br /> y =

哈哈哈 818

The C++ Programming Language第四版电子书pdf下载

Inside the C++ Object Model电子书pdf下载链接: https://pan.baidu.com/s/1xGphq5c7HueOWcYtLWupuQ 提取码获取方式:关注下面微信公众号,回复关键字:1178

欢迎关注微信公众号:DroidMind 1万+

The C Programming Language》(1)

为参加一次机试,我不得不重拾自从大学毕业后就再没用过的C。还好是机试,我可以自己选一本书研,不用忍受小强的唠里唠叨。说到选书,不禁又想起了大学时代K小强书的情景。小强的书讲的是真细,一不小心就掉入细节的汪洋大海中,爬都爬不出来。小强秉承了中国老师的一贯作风,对学生真是心贴心、手把手,硬是把一门编程语言嚼成一口一口的知识点,生怕学生们犯错。而且这种书巨好出题考你,甭管你程序写得怎么样,把小强的知识

风雨骑士 1792

C语言之父:我创造了C语言,但这些书帮我表达了出来 ...

C和c++是世界上最流行的两种计算机语言。 C是核心語言,C++是c语言的拓展。 这两种计算机语言的最大特征就是它们具有無限的可能性,这又是为何各种类型和不同经营规模的大型企业都采用它们,是因为它们具有可伸缩性和实用性。 随着计算机语言的发展,學習这门计算机语言的人数每秒钟都在增多。 如果你想学习C和c++,那麼选对你要的书毫无疑问是一个不错的选择。 ...

weixin_34336292的博客 947

The C Programming Language前言试译

我开始学习The C programming language一书,试着边边将英文译为中文。学习进度可能很慢。一句一句译,有的不一定精当。上传与同有此志向的朋友批评指正。

qq_31163099的博客 2385

The C Programming Language》答案(第一章)

The C Programming Language》答案(第一章) P1 #include <stdio.h> main() { printf("hello, world\n"); } P2 warning: unknown escape sequence: '\c' P3 #include <stdio.h> main() { float fahr,celsi...

SWY's Workshop 1万+

《c primer plus》、《The c programming language》中文译本,dev-c++编译器

如果你学c不只是为了考试的话,这两本最经典的c语言教程可能能帮到你 刚学c语言,用的谭浩强,谭老师的书,结果把书上原本的代码打到编译器上却总是出错{error},百度发现网上都是对谭老师这本书一面倒的负面评价。 但 如果你们学校规定的教材就是谭浩强的《c语言程序设计》,为了考试的话,那还是要看教材的,如果想对c理解的更深刻的话,这两本可以挑一本作为辅助提升。《c primer plu...

liloch的博客 1546

The C Programming Language》答案(第三章)

P1 #include <stdio.h> int binsearch(int x,int v[],int n){ int low = 0; int high = n-1; int mid; while(low<high){ mid = (low+high)/2; if(x<=v[mid]) ...

SWY's Workshop 1万+

【免费下载】 The C Programming Language(中文版).pdf

The C Programming Language(中文版).pdf 【下载地址】TheCProgrammingLanguage中文版.pdf分享 The C Programming Language(中文版).pdf 项目地址...

gitblog_06625的博客 6128

【亲测免费】 The C Programming Language - 中文版

The C Programming Language - 中文版 【下载地址】TheCProgrammingLanguage-中文版分享 《The C Programming Language》第二版,是一本学习C语言不可或缺的经典教材,由C语言之父丹尼斯·里奇(Dennis Ritchie)和布莱恩· Kernigha...

gitblog_06613的博客 1024

The C Programming Language资源下载介绍:学习C语言的全面资源库

The C Programming Language资源下载介绍:学习C语言的全面资源库 去发现同类优质开源项目:https://gitcode.com/ C语言作为计算机程序设计的基础,其经典之作——《C程序设计语言》一直是学习者的首选教材。今天,我们就来推荐一个开源项目,该项目提供了《C程序设计语言》的全面资源,助力编程爱好者深入学习这门经典语言。 项目介绍 The C Programming...

gitblog_06762的博客 867

【亲测免费】 《The C Programming Language》第二版练习题解答项目推荐

The C Programming Language》第二版练习题解答项目推荐 项目基础介绍和主要编程语言 该项目名为“The C Programming Language 2nd Edition - Solutions”,主要用于提供《The C Programming Language》(第二版)一书中所有练习题的解答。该书由Brian W. Kernighan和Dennis M. Ritc...

gitblog_00039的博客 660

【免费下载】 《The C Programming Language》(中文版):掌握C语言的权威指南

The C Programming Language》(中文版):掌握C语言的权威指南 【下载地址】TheCProgrammingLanguage中文版.pdf分享 The C Programming Language(中文版).pdf ...

gitblog_06660的博客 1232

The C Programming Language - 英文版 高清PDF下载

The C Programming Language - 英文版 高清PDF下载 【下载地址】TheCProgrammingLanguage-英文版高清PDF下载 《The C Programming Language》英文版高清PDF资源,专为追求优质阅体验的C语言学习者和开发者打造。该版本为非扫描版,确保文本清晰、...

gitblog_06770的博客 730

The-C-Programming-Language-2nd-Edition 项目常见问题解决方案

The-C-Programming-Language-2nd-Edition 项目常见问题解决方案 项目基础介绍 The-C-Programming-Language-2nd-Edition 是一个开源项目,旨在提供《The C Programming Language》第二版的源代码和练习解决方案。该项目由 Brian W. Kernighan 和 Dennis M. Ritchie 编写,是学...

gitblog_01188的博客 584

【亲测免费】 探索C语言的精髓:《The C Programming Language》第二版中文版推荐

探索C语言的精髓:《The C Programming Language》第二版中文版推荐 【下载地址】TheCProgrammingLanguage-中文版分享 《The C Programming Language》第二版,是一本学习C语言不可或缺的经典教材,由C语言之父丹尼斯·里奇(Dennis Ritchie)和...

gitblog_06640的博客 469
上一篇: 一个位运算的问题
下一篇: 不要返回指向局部变量的指针
RiderOnStorm
博客等级 码龄24年 27粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值