C/C 编程新手错误语录

2008-02-23 05:24:03来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

 1.引言

  还记得当年学数学、英语都有个窍门,那就是搞个错题集。经常复习一下这个错题集,就能够避免下次犯同样的错误。而几乎任何的程式员都是从犯错误开始的,我们也很有必要总结一下编程新手的常见错误,本文的目的在于此。文中所列出的都是笔者在项目研发中接触到的新手真实的言谈,笔者学学文革腔调,姑且称之为“错误语录”。

  2.语录

  (1)“我的程式都是对的,可结果不对”

  想想您的周围,是不是也有人说这样的话?假如您也曾说过,那就此打住,不要再说这句话,因为这句话只会显示说话者的无知。既然程式都是对的,那为什么结果不对?

  (2)“程式=算法 数据结构”

  假如刚刚学完C语言,我们说这样的话,完万能够理解,而且能够说是正确的。但是假如您是一位即将从事C/C 编程的程式员,那么很遗憾,这个说法只能判错,殊不知,世界上更有另一种说法:

  程式 = 对象  消息

  “程式=算法 数据结构”只对面向过程的语言(C)成立,而对面向对象的语言(C ),则只能表述为“程式=对象 消息”。传统的过程式编程语言以过程为中央以算法为驱动,面向对象的编程语言则以对象为中央以消息为驱动。这里的消息是广义的,对象A调用了对象B的成员函数,可看作对象A给B发消息。

  (3)“程式编出来,运行正确就行了”

  运行正确的程式并不一定是好程式,程式员时刻要牢记的一条就是自己写的程式不但是给自己看的,要让别人也能轻易地看懂。很遗憾,许多的编程新手不能清楚地驾驭软件的结构,对头文档和实现文档的概念含糊不清,写出来的程式可读性很差。

  C程式采用模块化的编程思想,需合理地将一个很大的软件划分为一系列功能单独的部分合作完成系统的需求,在模块的划分上主要依据功能。模块由头文档和实现文档组成,对头文档和实现文档的正确使用方法是:

  规则1 头文档(.h)中是对于该模块接口的声明,接口包括该模块提供给其他模块调用的外部函数及外部全局变量,对这些变量和函数都需在.h中文档中冠以extern关键字声明;

  规则2 模块内的函数和全局变量需在.c文档开头冠以static关键字声明;

  规则3 永远不要在.h文档中定义变量;

  许多程式员对定义变量和声明变量混淆不清,定义变量和声明变量的区别在于定义会产生内存分配的操作,是汇编阶段的概念;而声明则只是告诉包含该声明的模块在连接阶段从其他模块寻找外部函数和变量。如:

/*模块1头文档:module1.h*/
int a = 5; /* 在模块1的.h文档中定义int a */
/*模块1实现文档:module1 .c*/
#include “module1.h” /* 在模块1中包含模块1的.h文档 */
/*模块2实现文档: module2.c*/
#include “module1.h” /* 在模块2中包含模块1的.h文档 */
/*模块2 实现文档:module3 .c*/
#include “module1.h” /* 在模块3中包含模块1的.h文档 */

  以上程式的结果是在模块1、2、3中都定义了整型变量a,a在不同的模块中对应不同的地址单元,这明显不符合编写者的本意。正确的做法是:

/*模块1头文档:module1.h*/
extern int a; /* 在模块1的.h文档中声明int a */
/*模块1实现文档:module1 .c*/
#include “module1.h” /* 在模块1中包含模块1的.h文档 */
int a = 5; /* 在模块1的.c文档中定义int a */
/*模块2 实现文档: module2 .c*/
#include “module1.h” /* 在模块2中包含模块1的.h文档 */
/*模块3 实现文档: module3 .c*/
#include “module1.h”   /* 在模块3中包含模块1的.h文档 */

  这样假如模块1、2、3操作a的话,对应的是同一片内存单元。

  规则4 假如要用其他模块定义的变量和函数,直接包含其头文档即可。

  许多程式员喜欢这样做,当他们要访问其他模块定义的变量时,他们在本模块文档开头添加这样的语句:

extern int externVar; 

  抛弃这种做法吧,只要头文档按规则1完成,某模块要访问其他模块中定义的全局变量时,只要包含该模块的头文档即可。

  (4)“数组名就是指针”

  许多程式员对数组名和指针的区别不甚明了,他们认为数组名就是指针,而实际上数组名和指针有很大区别,在使用时要进行正确区分,其区分规则如下:

  规则1 数组名指代一种数据结构,这种数据结构就是数组;

  例如:

char str[10];
char *pStr = str;
cout << sizeof(str) << endl;
cout << sizeof(pStr) << endl;

  输出结果为:

10
4

  这说明数组名str指代数据结构char[10]。

  规则2 数组名能够转换为指向其指代实体的指针,而且是个指针常量,不能作自增、自减等操作,不能被修改;

char str[10];
char *pStr = str;
str ; //编译出错,提示str不是左值 
pStr ; //编译正确

  规则3 指向数组的指针则是另外一种变量类型(在WIN32平台下,长度为4),仅仅意味着数组的存放地址;

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: C 箴言:最小化文档之间的编译依赖

下一篇: 对C/C 可变参数表的深层探索