《征服C指针》试读:第0章:本书的目标与结构——引言

  0.1 本书的目标   在C语言的学习中,指针的运用被认为是最大的难关。   关于指针的学习,我们经常听到下面这样的建议: “如果理解了计算机的内存和地址等概念,指针什么的就简单了。”   “因为C是低级语言,所以先学习汇编语言比较好。”   果真如此吗?   正如那些C语言入门书籍中提到的那样,变量被保存在内存的“某个地方”。为了标记变量在内存中的具体场所,C语言在内存中给这些场所分配了编号(地址)。因此,大多数运行环境中,所谓的“指针变量”就是指保存变量地址的变量。   到此为止的说明,所有人都应该觉得很简单吧。   理解“指针就是地址”,可能是指针学习的必要条件,但不是充分条件。现在,我们只不过刚刚迈出了“万里长征的第一步”。   如果观察一下菜鸟们实际使用C指针的过程,就会发现他们往往会有如下困惑。 声明指针变量int a;……到这里还挺像样的,可是当将这个变量作为指针使用时,依然悲剧地写成了a。 给出int &a;这样的声明(这里不是指C++编程)。 啥是“指向int的指针”?不是说指针就是地址吗?怎么还有“指向int的指针”,“指向char的指针”,难到它们还有什么不同吗? 当学习到“给指针加1,指针会前进2个字节或者4个字节”时,你可能会有这种疑问:“不是说指针是地址吗?这种情况下,难道指针不应该是前进1个字节吗?” scanf()中,在使用%d的情况下,变量之前需要加上&才能进行传递。为什么在使用%s的时候,就可以不加&? 学习到将数组名赋给指针的时候,将指针和数组完全混为一谈,犯下“将没有分配内存区域的指针当做数组进行访问”或者“将指针赋给数组”这样的错误。   出现以上混乱的情形,并不是因为没有理解“指针就是地址”这样的概念。其实,真正导演这些悲剧的幕后黑手是: C语言奇怪的语法 数组和指针之间微妙的兼容性   某些有一定经验的C程序员会觉得C的声明还是比较奇怪的。当然也有一些人可能并没有这种体会,但或多或少都有过下面的疑问。 C的声明中,[]比的优先级高。因此,char s[10]这样的声明意为“指向char的指针的数组”——搞反了吧? 搞不明白double (p)[3];和void (func)(int a);这样的声明到底应该怎样阅读。 int a中,声明a为“指向int的指针”。可是表达式中的指针变量前却代表其他意思。明明是同样的符号,意义为什么不同? int a和int a[]在什么情况下可以互换? 空的[]可以在什么地方使用,它又代表什么意思呢?   本书的编写就是为了回答以上这样的问题。   很坦白地说,我也是在使用了C语言好几年之后,才对C的声明语法大彻大悟的。   世间的人们大多不愿意承认自己比别人愚笨,所以总是习惯性地认为“实际上只有极少的人才能够精通C语言指针”,以此安慰一下自己那颗脆弱的心。   例如,你知道下面的事实吗? 在引用数组中的元素时,其实a[i]中的[]和数组毫无关系。 C里面不存在多维数组。   如果你在书店里拿起这本书,翻看几页后心想:“什么呀?简直是奇谈怪论!”然后照原样把书轻轻地放回书架。那么你恰恰需要阅读这本书。   有人说:“因为C语言是模仿汇编语言的,要想理解指针,就必须理解内存和地址等概念。”你可能会认为:   “指针”是C语言所特有的、底层而邪恶的功能。   其实并不是这样的。确实,“C指针”有着底层而邪恶的一面,但是,它又是构造链表和树等“数据结构”不可缺少的概念。如果没有指针,我们是做不出像样的应用程序的。所以,凡是真正成熟的开发语言,必定会存在指针,如Pascal、Delphi、Lisp和Smalltalk等,就连Visual Basic也存在指针。早期的Perl因为没有指针而饱受批评,从版本5开始也引入了指针的概念。当然,Java也是有指针的。很遗憾,世上好像对此还存有根深蒂固的误解。   在本书中,我们将体验如何将指针真正地用于构造数据结构。   “指针”是成熟的编程语言必须具有的概念。   尽管如此,为什么C的指针却让人感觉格外地纠结呢?理由就是,C语言混乱的语法,以及指针和数组之间奇怪的兼容性。   本书旨在阐明C语言混乱的语法,不但讲解了“C特有的指针用法”,还针对和其他语言共有的“普遍的指针用法”进行了论述。   下面,让我们来看一下本书的具体结构。 0.2 目标读者和内容结构   本书的目标读者为: 粗略地读过C语言的入门书籍,但还是对指针不太理解的人 平时能自如地使用C语言,但实际对指针理解还不够深入的人   本书由以下内容构成。 第1章:从基础开始——预备知识和复习 第2章:做个实验见分晓——C是怎样使用内存的 第3章:揭秘C的语法——它到底是怎么回事 第4章:数组和指针的常用用法 第5章:数据结构——真正的指针的使用方法 第6章:其他——拾遗   第1章和第2章主要面向初学者。从第3章开始的内容,是为那些已经具备一定经验的程序员或者已经读完第1章的初学者准备的。   面向初学者,第1章和第2章从“指针就是地址”这个观点开始讲解。   通过printf()来“亲眼目睹”地址的实际值,应该说,这不失为理解指针的一个非常简单有效的方式。   对于那些“尝试学习了C语言,但是对指针还不太理解”的人来说,通过自己的机器实际地输出指针的值,可以相对简单地领会指针的概念。   首先,在第1章里,针对C语言的发展过程(也就是说,C是怎样“沦为”让人如此畏惧的编程语言的)、指针以及数组进行说明。   对于指针和数组的相互关系,市面上多数的C语言入门书籍只是含混其辞地做了敷衍解释(包括K&R*,我认为该书是诸恶之源)。这还不算,他们还将本来已经用数组写好的程序,特地用指针运算的方式重新编写,还说什么“这样才像C语言的风格”。   像C语言的风格?也许是可以这么说,但是以此为由炮制出来的难懂的写法,到底好在哪里? 哦?执行效率高?为什么?这是真的吗?   产生这些疑问是正常的,并且,这么想是正确的。   了解C语言的发展过程,就能理解C为什么会有“指针运算”等这样奇怪的功能。   第1章中接下来的内容也许会让初学者纠结,因为我们将开始接触到数组和指针的那些容易让人混淆的语法。   第2章讲解了C语言实际上是怎样使用内存的。   在这里同样采用直观的方式将地址输出。请有C运行环境的读者一定亲手输入例程的代码,并且尝试运行。   对于普通的局部变量、函数的参数、static变量、全局变量及字符串常量(使用" "包围的字符串)等,知晓它们在内存中实际的保存方式,就可以洞察到C语言的各种行为。   遗憾的是,几乎所有使用C语言开发的程序,运行时检查都不是非常严密。一旦出现诸如数组越界操作,就会马上引起“内存区域破坏”之类的错误。虽然很难将这些bug完全消灭,但明白了C如何使用内存之后,至少可以在某种程度上预防这些bug的出现。   第3章讲解了与数组和指针相关的C语言语法。   虽然我多次提到“究竟指针为什么这么难”,但是对于“指针就是地址”这个观点,在理解上倒是非常简单。出现这种现象,其实缘于C语言的数组和指针的语法比较混乱。   乍看上去,C语言的语法比较严谨,实际上也存在很多例外。   对于那些平时和我们朝夕相处的语法,究竟应套用哪条规则?还有,哪些语法需要特殊对待?关于这些,第3章里会做彻底的讲解。   那些自认为是老鸟的读者,可以单独拿出第3章来读一读,看看自己以前是如何上当的。   第4章是实践篇,举例说明数组和指针的常用用法。如果读者理解了这部分内容,对付大部分程序应该不在话下。   老实说,对于已经将C语言使用得像模像样的读者来说,第4章中举出的例子并没有什么新意。但是,其实有些人对这些语法只是一知半解,很多时候只不过是依照以前的代码“照猫画虎”罢了。   阅读完第3章后去读第4章,对于那些已经能够熟练使用的写法,你也会惊呼一声:“原来是这个意思啊!”   第5章中,解说指针真正的用法——数据结构的基本知识。   前四章中的例子,都是围绕C语言展开的。第5章里则会涉及其他语言的指针。   无论使用哪种语言编程,“数据结构”都是最重要的。使用C语言来构造数据结构的时候,结构体和指针功不可没。   “不仅仅对于C语言的指针,连结构体也不太明白”的读者,务必不要错过第5章。   第6章中,对到此为止还没有覆盖到的知识进行拾遗,并且为大家展示一些可能会遇到的陷阱以及惯用语法。   和类似的书籍相比,本书更加注重语法的细节。   提起语法,就有“日本的英语教育不偏重语法”,以至于给人“就算不明白也没有什么”的印象。确实是这样,我们早在不懂“サ行”怎样变形之前,就已经会说日语了。   但是,C语言可不是像日语那样复杂的自然语言,它是一门编程语言。   单纯地通过语法来解释自然语言是非常困难的。比如,日语“いれたてのおちゃ”,利用假名汉字变换程序只能变换成“淹れたてのお茶”(中文意思是‘沏好的茶’),尽管如此,同样通过假名变换程序,“いれたてのあついおちゃ”竟然也可以变换成“入れた手の厚いお茶” (中文意思是‘沏好的热腾腾的茶’)[ 中文里也有类似的例子,如:他是先知。→他是先知道那件事的人。——译者注]。编程语言最终还是通过人类制订的语法构成的,它要做到让编译器这样的程序能够解释。 “反正大家都是这么写,我也这么写,程序就能跑起来。” 这种想法,让人感觉有点悲哀。   我希望不仅是初学者,那些已经积累了一定经验的程序员也能阅读本书。通过深入理解C的语法,可以让我们真正领会直到今天还像“口头禅”一样使用的那些程序惯用写法。   无论如何,让我们做到“知其然知其所以然”,这样有利心理健康,不是吗?   

>征服C指针

征服C指针
作者: 前桥和弥
isbn: 7115301212
书名: 征服C指针
页数: 254
译者: 吴雅明
定价: 49.00元
出版社: 人民邮电出版社
出版年: 2013-2