读书笔记之The C Programming Language

最近找工作,发现一个很尴尬的事情,研究生阶段主要做的都是研究方向的问题,应该算是偏向于软件以及算法(其实也就是编程实现一些cv的算法,常用语言matlab),所以就在软件方向找了份软件开发工程师的工作。因为机试用的是C语言,而本科学得C语言都还给老师了,所以紧急学了两天,总算还没忘干净,最终拿到了offer,虽然如此,但是以后还是要用到的,所以还是利用十一重新学习了一下。因为c语言的书太多了,大部分都据说很烂(话说我们学的谭浩强的书,个人感觉就很恐怖,感觉就不是把你往明白的方向教),所以选了一部比较好的书“The C Programming Language”,就是那本霸气的K&R C Bible(话说是印在书的封面上的哦!)。读完后觉得称之为Bible还是应该的,不是因为这本书的作者是C语言的开发者,也不是因为大家都推荐它,而是因为这本书能很条理的讲述C语言的知识,一步一步的教你怎样写能够用的上的函数,在函数的编程中理解各种基本知识与概念,而不是做那种凭空想出来的题目。而且我觉得看英文版的能够比较效率的学习,因为经过了一层的翻译,尤其是很烂的翻译后,总会丢失一些东西,而且很多概念英文是很清晰的,而翻译过来有时真的会莫名其妙,最重要的是,看英文原版的书,能够更加专心,更加用心的去理解,不会那么浮躁(可能是我自己的毛病),因此能够收获更多。

下面是对这本书的一些总结,算是读书笔记吧。

第一章:tutorial introduction

是全书的一个tutorial introduction,基本覆盖了c语言的大部分基本内容,当然指针,结构这些内容还是c语言中比较高阶的东西,所以没有覆盖。首先是Hello World函数,这个就不说了。然后是一个温度转换函数,这个函数基本覆盖了变量定义,循环,表达式,以及格式化输出等内容,这个算是一个比较有意义的完整的c程序了。本章内容还包括了for循环,宏定义,字符输入输出,数组,函数,值传递,字符数组,外部变量与作用域等内容,比较全面而且简单的对这些知识做了一定的介绍,后面的章节会在这个上面展开。

第二章:Types,Operators,and Expressions

本章按照标题来看是分成了3个部分,类型,运算符,表达式。

首先介绍了variable name:数字,字母,下划线(不能以数字开头,也不推荐以下划线开头,因为库文件是以下划线开头的)。还不能用关键字

Data Type:char,int,float,double是最基本的数据类型,当然加上short,long,unsigned,signed修饰符,可以得到更加丰富的类型。

Constants:与变量对应的就是常量,字符常量可以看成是整数。

Type Conversion:这里有一个点就是强制类型转换,(type_name) expression

Bitwise Operators: 能够实现一些逻辑检验的问题。

Precedence:优先级,其实本章最重要的部分应该就是这里了。各种operators都是比较简单好记的,唯有优先级问题是比较难记的,若是每次都查的话太没水平了,也绝对不利于理解后面的函数,这个应该算是基本功。总的顺序是unary>binary.优先级最高的严格意义上说不算operator,这些是括号(),数组索引括号[],结构成员选择符(->,.)。然后是剩下的一元运算符,非,取反,自增,自减,类型转换,指针,取址,sizeof。这一组的连接方式是right to left。然后是2维运算符,算术>移位>关系>逻辑。然后是一个right to left的三维运算符,然后是赋值运算符,最后是逗号运算符。

第三章:Control Flow

一门编程语言的语句有三种:顺序,条件,和循环,这就构成了编程语言的控制流,3种简单的控制语句构成了各种强大的程序,甚至是一些神一样的程序,这确实是一件很amazing的事情。条件语句有if-else,elseif,switch。switch是需要注意的,这个是条件分支结构,常常需要跟break结合在一起发挥作用,一般情况下case后面都要加上break,如果不加的话,会继续执行下一条case,一直到遇到break为止。但是有些程序在需要的情况下不在每一个case后面加上break,这样会产生有益的效果,这也是需要注意的(这种情况下最好注释说明一下)。循环语句有while,do-while,for三种。本章中写的比较有意义的程序有shell sort,bin-search以及alpha-num count。当然还有诡异的goto语句,其实个人觉得goto语句还是很有意义的啊,可以快速跳出循环,跳到下个执行的地方,代价会是搞得程序比较混乱。但是书中作者和各位老师都不提倡用goto,并且不用goto也能写出很好的程序,所以就never mind吧。

第四章:Function and Program Structure

c语言最重要的就是函数,c就是由函数构成的,程序的主体是包含在main{}中的部分,main函数也是函数,有着与其他函数一样的性质,比如说作用域,参数,返回值的问题等等。函数有声明和定义,在用到一个函数之前必须先声明。函数可以声明多次,但是只能定义一次。c语言不允许在函数中定义函数,这和matlab等是不一样的,因为程序都是并列存在的,所以所有的函数都是external。变量也分为外部变量和内部变量。内部变量的作用域是函数本身,外部变量的作用域是程序的整个执行空间。静态变量static是用在外部变量和函数的修饰符,表明这些函数或变量的作用域只是到此源文件的结尾。寄存器变量register,是定义在了计算机的寄存器上的变量,应该说在运行速度上肯定是很有优势的,但是实际意义,还没怎么看得到。递归,是一个很神奇的东西,它能很大程度上简化程序的复杂度,但是缺点是,时间复杂度太大。递归在数据结构上会有很大应用,尤其是tree。递归必须要有一个终止条件,否则就是死循环。最后本章还包含了宏替换的内容,需要注意的是要给每个变量加上括号,如#define max(A,B) ((A)>(B)?(A):(B)),否则后果会很严重。本章写了相当多的有意义的函数,如getline,strindex,atof,出入栈函数(push,pop),getch和ungetch,快速查找quicksort,以及取最大值的宏替换等等。同时也很系统的做了一个计算器的程序,用到了子函数,外部变量,栈等等,算是一个比较完备的程序了。

第五章:Pointers and Arrays

指针才是c语言的精华所在。如果学c语言不学指针或者说不懂指针的话,那就只能呵呵了。从全书来看,pointer绝对是重中之重,函数的形参定义要用到,结构的定义要用到,数据结构也要用到,前面的内容,其实各种编程语言都是差不多的,懂了一种编程语言,那么基本上看看就能掌握,但是这对指针不适用。指针应该是c语言的独创,c语言30年不倒,跟指针应该说是有很大关系的,c与底层硬件的紧密联系应该说指针也是有功劳的。指针是包含变量地址的变量,因此指针也是变量(这一点很重要)。指针的一个比较大的用处应该是在函数的形参声明上,因为c语言的函数是值传递的,因此如果用普通的int等变量定义函数的行参,那么实际上函数运行的时候,只是修改的是输入的变量的副本,对实参是没有任何改变的,因此其实是什么都没有做的,这跟c语言的值传递,以及作用域原则有关。而指针和数组则不存在这样的问题,数组和指针在相当大的程度上是相通的,而且指针比较简洁,所以形参声明会用到指针。指针指向的是数组的元素,p是指针,a[]是数组,那么p=a;指针指向数组时是可以做加减法的,当然要在数组的索引范围内。指针和数组名的区别是指针是变量,而数组名不是,这也就意味着不可以做b=a以及a++这样的事情。指向指针的指针,也就是指针数组,就相当于是数组中存的内容是指针,我觉得这个主要是为了替代多维数组而存在的。而指针数组相对比多维数组的优点是不用为每个子数组定义相同大小的空间。指向函数的指针,函数不是变量,但是可以定义指向函数的指针,我觉得意义就在于可以让程序选择在不同情况下用哪个函数,例如(int ()(void,void*))(numeric?numcmp:strcmp),numcmp和strcmp是两个函数。另外本章还提到了命令行参数,args(命令行参数的个数),argv[](指向命令行参数的指针数组)。这一章写了更多的函数swap,strlen,alloc,strcmp,strcpy,getline,writeline,重写的qsort函数等等。

第六章:Structure

我感觉structure就是为了构建数据结构而存在的!Structure是用于构建属于自己的data type,就像int,char一样,实际而言,他们的用法是一样的。因此,自然就会有pointer,function,array等等内容。还有结构的自引用,有点递归的意思,这个在构建tree结构的时候有了很好的应用。Union的用处在于程序的兼容,当定义变量时,我们不确定要定义成什么类型时,也即不知到该分配多少空间时,union可以表现一下。本章的另一个比较重要的点是:typedef。typedef并不能创建一个新的数据类型,他只是把原有的数据类型又重新定义了一个名字,看上去没什么用,但是真的没用么?当然不是,这么做的目的一个是可移植性,因为不同的machine对于int(举个例子)的空间分配是不同的,所以当需要移植的时候,只需要修改typedef就可以了;第二个就是能使变量的意义更明了,比如typedef inttreeptr,当定义int型的树指针时,用treestr更加清晰。本章的程序主要是keyword_count,tree,以及table_lookup,其中tree这个函数系列涉及到了C语言的很多方面,作为一个例子来说,比较有深度。

第七章:Input and Output

本章介绍了一些输入输出的接口函数,getchar,putchar, printf, scanf, sprintf, sscanf, getc, putc, fopen, fclose,stdin, stdout, fputs, fgets. 并且介绍了几个比较有用的头文件:,, .

本书还有两个附录:一个是Reference Manual, 另一个是Standard Library. 有时间要翻翻看看。