1回顶部 前文回顾:C/C++编程新手错误语录 错误语录(续一) (13)“整型变量仅仅意味着一个整数” 当我们还是一个新手,看整型就是整数; //启动任务1 在此提出“泛整型”的概念,(unsigned)char、(unsigned)short int、(unsigned)int、(unsigned)long int等都属于这个范畴,指针必然属于“泛整型”的范围。用指针的高超境界,也为将其看做一个“泛整型”。 看看软件的详细设计文档,其数据结构定义部分经常看到“INT8、UINT8、INT16、UINT16、INT32、UINT32、INT64、UINT64”或“BYTE、WORD、DWORD”等数据类型,它们在本质上都是(unsigned)char、(unsigned)short int、(unsigned)int、(unsigned)long int宏定义的结果,都属于“泛整型”。所以,“泛整型”的概念真实地体现在日常的软件设计当中。 2回顶部 正因为各种指针类型在本质上都是“泛整型”,因此它们可以互相转化: int a, b; 等价于: int a, b; 从来没有人会用memset( (char*) &a, (char*) &b, sizeof(int) )来代替a = b,这里只是为了说明问题。下面的代码则经常用到: int *p = (int *) malloc(100*sizeof(int)); 我们看memset的函数原型为: void * memset ( void * buffer, int c, size_t num ); 实际上它接受的第一个参数是无类型指针,在memset函数体内,其它任意类型的指针都向void *转化了。类似的内存操作函数memcpy所接受的源和目的内存地址也是无类型指针。 char *转化为int *后的值虽然不变(还是那个地址),但是其++、--等操作的含义却发生了变化,这也是要注意的。 char *p; 与 char *p; 的结果是不一样的,前者的p值加了1,而后者的则增加了sizeof(int)。 下面来剥Windows程序设计中消息传递函数两个参数的皮,看看它们究竟是什么: typedef UINT WPARAM; 原来,WPARAM和LPARAM其实都属于“泛整型”,所以不要报怨消息处理函数只能接受“泛整型”。实际上,从指针的角度上来讲,在C/C++中,可以获得任何类型实例(变量、结构、类)的指针,所以Windows的消息处理函数实际上可以接受一切类型的参数。 惊天动地一句话:“泛整型”可表征一切。 3回顶部 (14)“值传递一定不会改变参数” 理论而言,值传递的确不会改变参数的内容。但是,某年某月的某一天,隔壁office的硕士mm写了这么一段程序,参数的值却被改变了: int n = 9; 大概整个office的人都被搞懵了,都说编译器瞎搞,有问题。找到笔者,笔者凭借以往的经常,一眼就看出来不是什么编译器出错,而是在函数example内对字符串a的访问越界! 当在函数example内对a的访问越界后,再进行写操作时,就有可能操作到了n所在的内存空间,于是改变了n的值。 给出这个语录,并非为了推翻“值传递不会改变参数”的结论,而是为了从侧面证明在C/C++语言中,数组越界是多么危险的错误! 下面的两个函数有明显的数组越界: void example1() 而这个函数的越界就不这么明显: void example3() 其实,这个函数危险到了极点。因为对于strcpy函数而言,拷贝的时候要碰到’\0’才结束,str1并没有被赋予结束符,因而你根本就不知道strcpy( string, str1 )的结果究竟会是拷贝多大一片内存! 遗憾的是,C/C++永远不会在编译和连接阶段提示数组越界,它只会在运行阶段导致程序的崩溃。 数组越界,是大多数C/C++编程新手常犯的错误,而它又具有极大的隐蔽性,新手们一定要特别注意。 4回顶部 (15)“C不高级,学C++、JAVA、C#才够味” 也许谭浩强老师的C语言教材是绝大多数高校学生学习的第一门编程课程,所以在许多学生的心目中,觉得C是一种入门级的语言,他们舍弃基础而追逐花哨的Visual XXX、Java、ASP、PHP、.net,他们以为这样做“赚大了”。 非也! C是一种多么富有魅力的语言!在今时的绝对多数底层开发中,仍然几乎被C完全垄断。这些领域包括操作系统、嵌入式系统、数字信号处理等。舍弃C的经济基础搭.net的高层建筑实在是危险。 我们总是以为自己掌握了C,那么请写一个strcpy的标准函数。您的答案若是: void strcpy( char *strDest, char *strSrc ) 很遗憾,您的程序只能拿到E。看看拿A的strcpy: char * strcpy( char *strDest, const char *strSrc ) 这个程序考虑了什么? (1)程序要强大:为了实现链式操作,将目的地址返回,函数返回类型改为char * (2)程序要可读:源字符串指针参数加const限制,表明为输入参数 (3)程序要健壮:验证strDest和strSrc非空 如果这三点中您只考虑到0点或1点,那么请回家好好修炼一下C。因为这个最简单的strcpy已验证出您的C语言基础只能叫做“入门”。 再写个简单的strlen,这么写就好了: int strlen( const char *str ) //输入参数为const 由此可见,写好这些简单的函数也需要深厚的基本功,永远不要放弃对基本功的培养。 5回顶部 (16)“语言学得越多越好” 许多的初学者都经历过这样的一个阶段,面对大量的编程语言和开发环境,他们俩感到难以取舍,不知道自己究竟应该学习什么。于是他们什么都学,今天看一下Visual Basic,明天看学一下C++,后天在书点看到了本Java便心血来潮买回来翻翻,大后天又发现必须学.net了。他们很痛苦,什么都在看,结果什么都没学会,忙忙碌碌而收获甚微。 我们真的没有必要在什么语言都不甚精通的情况下乱看一气。认准了一种真正语言就应该坚持不懈地努力。因为任何一门语言的掌握都非一朝一夕一事,笔者从六年前开始接触C++,直到现在,每一阶段仍有新的启发,在项目开发的过程中也不断有新的收获。今日我还是绝对不敢宣称自己“精通”这门语言。 许多刚毕业的大学生,动不动就在简历上写上自己精通一堆语言。与之相反,大多数优秀的工程师都不敢这么写。也许,研究越深,便越敢自身的无知。 在下认为,一个成熟的语言体系应该是: 程序员的语言体系 = 一种汇编 + C + 一种面向对象(C++、JAVA、C#等) 如果还要加,那就加一种解释型语言,perl或tcl(也许其它)。 语言具有极大的相似性,从C++过渡到JAVA只需要很短的一段时间。各种语言的发展历史也体现了编程思想的发展史。我们学习一种语言,语法也许并不是最重要的,最重要的是蕴藏在语法外表下的深层特性和设计用意。 本回书着落此处,更多错误语录,当然是待续。 |
閺€鎯版閹存劕濮�閺屻儳婀呴弨鎯版>>

相关文章
visual c++ 6.0怎么编译运行?visual c++ 6.0编译运行教程
visual c++ 6.0怎么用?visual c++ 6.0使用方法
vs2015中文旗舰版编写c++程序的操作教程
vc++6.0(Visual C++)的使用操作步骤
visual c++ 6.0怎么显示行号
visual c++ 2008运行库怎么装在c盘 visual c++ 2008运行库装在c盘的方法
microsoft visual c++ 2008怎么安装 microsoft visual c++ 2008安装方法
Visual Studio 2010编写C++程序的具体步骤
vc++6.0Visual C++进行安装的操作过程讲解
Notepad++配置C++环境的操作步骤