C语言之精华总结由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“c语言之精华总结”。
从研究生二年纪开始学习计算机也差不多两年了,一路走来,有很多的收获,也有不少的遗憾,现在正好有一段闲暇,就想对走过的路留下一些足迹,回忆。每个人都有自己不同的人生,说到这里,就是程序人生了,歌德在《浮士德》中说过:―如果不曾在悲哀中咀嚼过面包,不曾在哭泣中等待过明天,这样的人就不知道你——天的力量。‖所以我想记下一些带给我悲哀,带给我哭泣的程序人生。其实学习计算机的基础课程是非常重要的,离散数学,编译原理,操作系统,形式语言……,如果你认真走过了这些路,在以后的日子你会发现你的路会越走越宽,以前的努力和汗水会不断的给你灵感,给你支持,给你前进的武器和勇气。你会发现以后取得的很多成就,不过是朝花夕拾而已!
对于程序语言我喜欢的是C++,它能带给你别的语言无法给予你的无上的智力快感,当然也会给你一门语言所能给你的魔鬼般的折磨。其实Java,C#,Python语言也非常的不错,我也极为喜欢。它们都是非常成功的语言,我从来就不愿意做某一种语言的盲目信仰者,每种语言都有它成功的地方,失败的地方,都有它适合的地方,不如意的地方。所以每一次看到评价语言的文章,我看看,但从来不会发言。
C++的前世是C,而且C所留下的神秘以及精简在C++中是青出于蓝而胜于蓝!C所带给人的困惑以及灵活太多,即使一个有几年经验的高段C程序员仍然有可能在C语言的小水沟里翻船。不过其实C语言真的不难,下面我想指出C语言中最神秘而又诡谲多变的四个地方,它们也继续在C++语言中变幻莫测。指针,数组,类型的识别,参数可变的函数。一.指针。
它的本质是地址的类型。在许多语言中根本就没有这个概念。但是它却正是C灵活,高效,在面向过程的时代所向披靡的原因所在。因为C的内存模型基本上对应了现在von Neumann(冯·诺伊曼)计算机的机器模型,很好的达到了对机器的映射。不过有些人似乎永远也不能理解指针【注1】。
注1:Joel Spolsky就是这样认为的,他认为对指针的理解是一种aptitude,不是通过训练就可以达到的
http://www.daodoc.com/wiki/APL_programming_language
下面有一段是这样的: APL is renowned for using a set of non-ASCII symbols that are an extension of traditional arithmetic and algebraic notation.These cryptic symbols, some have joked, make it poible to construct an entire air traffic control system in two lines of code.Because of its condensed nature and non-standard characters, APL has sometimes been termed a “write-only language”, and reading an APL program can feel like decoding an alien tongue.Because of the unusual character-set, many programmers used special APL keyboards in the production of APL code.Nowadays there are various ways to write APL code using only ASCII characters.在C++中有函数重载(overload)可以用来区别不同函数参数的调用,但它还是不能表示任意数量的函数参数。
在标准C语言中定义了一个头文件专门用来对付可变参数列表,它包含了一组宏,和一个va_list的typedef声明。一个典型实现如下【注14】: typedef char* va_list;#define va_start(list)list =(char*)&va_alist #define va_end(list)#define va_arg(list, mode)((mode*)(list += sizeof(mode)))[-1] 注14:你可以查看C99标准7.15节获得详细而权威的说明。也可以参考Andrew Konig的《C陷阱与缺陷》的附录A。ANSI C还提供了vprintf函数,它和对应的printf函数行为方式上完全相同,只不过用va_list替换了格式字符串后的参数序列。至于它是如何实现的,你在认真读完《The C Programming Language》后,我相信你一定可以do it yourself!使用这些工具,我们就可以实现自己的可变参数函数,比如实现一个系统化的错误处理函数error。它和printf函数的使用差不多。只不过将stream重新定向到stderr。在这里我借鉴了《C陷阱与缺陷》的附录A的例子。实现如下: #include #include
void error(char* format, …){ va_list ap;va_start(ap, format);fprintf(stderr, ―error: ―);vfprintf(stderr, format, ap);va_end(ap);fprintf(stderr, ―n‖);exit(1);} 你还可以自己实现printf: #include
int printf(char* format, …){ va_list ap;va_start(ap, format);int n = vprintf(format, ap);va_end(ap);return n;} 我还专门找到了VC7.1的头文件看了一下,发现各个宏的具体实现还是有区别的,跟很多预处理(preproceor)相关。其中va_list就不一定是char*的别名。typedef struct { char *a0;/* pointer to first homed integer argument */ int offset;/* byte offset of next parameter */ } va_list;其它的定义类似。
经常在Windows进行系统编程的人一定知道函数调用有好几种不同的形式,比如__stdcall,__pascal,__cdecl。在Windows下_stdcall,__pascal是一样的,所以我只说一下__stdcall和__cdecl的区别。
(1)__stdcall表示被调用端自身负责函数引数的压栈和出栈。函数参数个数一定的函数都是这种调用形式。
例如:int fun(char c, double d),我们在main函数中使用它,这个函数就只管本身函数体的运行,参数怎么来的,怎么去的,它一概不管。自然有main负责。不过,不同的编译器的实现可能将参数从右向左压栈,也可能从左向右压栈,这个顺序我们是不能加于利用的【注15】。
注15:你可以在Herb Sutter的《More Exceptional C++》中的条款20:An Unmanaged Pointer Problem, Part 1:Parameter Evaluation找到相关的细节论述。
(2)__cdecl表示调用端负责被调用端引数的压栈和出栈。参数可变的函数采用的是这种调用形式。
为什么这种函数要采用不同于前面的调用形式呢?那是因为__stdcall调用形式对它没有作用,被调用端根本就无法知道调用端的引数个数,它怎么可能正确工作?所以这种调用方式是必须的,不过由于参数参数可变的函数本身不多,所以用的地方比较少。
对于这两种方式,你可以编制一些简单的程序,然后反汇编,在汇编代码下面你就可以看到实际的区别,很好理解的!重载函数有很多匹配(match)规则调用。参数为―…‖的函数是匹配最低的,这一点在Andrei Alexandrescu的惊才绝艳之作《Modern C++ Design》中就有用到,参看Page34-35,2.7―编译期间侦测可转换性和继承性‖。后记:
C语言的细节肯定不会只有这么多,但是这几个出现的比较频繁,而且在C语言中也是很重要的几个语言特征。如果把这几个细节彻底弄清楚了,C语言本身的神秘就不会太多了。C语言本身就像一把异常锋利的剪刀,你可以用它做出非常精致优雅的艺术品,也可以剪出一些乱七八糟的废纸片。能够将一件武器用到出神入化那是需要时间的,需要多长时间?不多,请你拿出一万个小时来,英国Exter大学心理学教授麦克.侯威专门研究神童和天才,他的结论很有意思:―一般人以为天才是自然而生、流畅而不受阻的闪亮才华,其实,天才也必须耗费至少十年光阴来学习他们的特殊技能,绝无例外。要成为专家,需要拥有顽固的个性和坚持的能力……每一行的专业人士,都投注大量心血,培养自己的专业才能。‖【注16】
注16:台湾女作家、电视节目主持人吴淡如《拿出一万个小时来》。《读者》2003.1期。―不用太努力,只要持续下去。想拥有一辈子的专长或兴趣,就像一个人跑马拉松赛一样,最重要的是跑完,而不是前头跑得有多快。‖ 推荐两本书:
K&R的《The C Programming language》,Second Edition。Andrew Konig的《C陷阱与缺陷》。本文从中引用了好几个例子,一本高段程序员的经验之谈。
但是对纯粹的初学者不太合适,如果你有一点程序设计的基础知识,花一个月的时间好好看看这两本书,C语言本身就不用再花更多的精力了