| 订阅 | 在线投稿
分享
 
 
当前位置: 王朝网络 >> c/c++ >> C/C++编程新手错误语录
 

C/C++编程新手错误语录

2008-06-01 02:04:59 编辑來源:互联网 繁體版 评论
 
 
  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的话,对应的是同一片内存单元。

  

C/C++编程新手错误语录
更多内容请看C/C++技术专题 java编程开发手册专题,或

  规则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),仅仅意味着数组的存放地址;

  规则4数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针;很遗憾,在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。

  例如:

  void arrayTest(char str[])

  {

  cout << sizeof(str) << endl;//输出指针长度

  str++; //编译正确

  }

  int main(int argc, char* argv[])

  {

  char str1[10] = "I Love U";

  arrayTest(str1);

  return 0;

  }

  (5)“整形变量为32位”

  整形变量是不是32位这个问题不仅与具体的CPU架构有关,而且与编译器有关。在嵌入式系统的编程中,一般整数的位数等于CPU字长,常用的嵌入式CPU芯片的字长为8、16、32,因而整形变量的长度可能是8、16、32。在未来64位平台下,整形变量的长度可达到64位。

  长整形变量的长度一般为CPU字长的2倍。

  在数据结构的设计中,优秀的程序员并不会这样定义数据结构(假设为WIN32平台):

  typedef strUCt tagTypeExample

  {

  unsigned short x;

  unsigned int y;

  }TypeExample;

  他们这样定义:

  #define unsigned short UINT16 //16位无符号整数

  #define unsigned int UINT32 //32位无符号整数

  typedef struct tagTypeExample

  {

  UINT16 x;

  UINT32 y;

  }TypeExample;

C/C++编程新手错误语录
更多内容请看C/C++技术专题 Java编程开发手册专题,或

  这样定义的数据结构非常具有通用性,假如上述32平台上的数据发送到16位平台上接收,在16位平台上仅仅需要修改UINT16、UINT32的定义:

  #define unsigned int UINT16 //16位无符号整数

  #define unsigned long UINT32 //32位无符号整数

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  几乎所有的优秀软件设计文档都是这样定义数据结构的。

  (6)“switch和if …else…可随意替换”

  switch语句和一堆if…else…的组合虽然功能上完全一样,但是给读者的感受完全不一样。if…else…的感觉是进行条件判定,对特例进行非凡处理,在逻辑上是“非凡与一般”的关系,而switch给人的感觉是多个条件的关系是并列的,事物之间不存在非凡与一般的关系,完全“对等”。

  譬如:

  //分别对1-10的数字进行不同的处理,用switch

  switch(num)

  {

  case 1:

  …

  case 2:

  …

  }

  //对1-10之间的数字进行非凡处理,用if

  if(num < 10 && num > 1)

  {

  …

  }

  else

  {

  …

  }

  许多时候,虽然不同的代码可实现完全相同的功能,但是给读者的感觉是完全不同的。譬如无条件循环:

  while(1)

  {

  }

  有的程序员这样写:

  for(;;)

  {

  }

  这个语法没有确切表达代码的含义,我们从for(;;)看不出什么,只有弄明白for(;;)在C/C++语言中意味着无条件循环才明白其意。而不懂C/C++语言的读者看到while(1)也可猜到这是一个无条件循环。

  (7)“免得麻烦,把类里面的成员函数都搞成public算了”

  

   许多人编C++程序的时候,都碰到这样的情况,先前把某个成员函数定义成类的PRivate/protected函数,后来发现又要从外面调用这个函数,就轻易地将成员函数改为public类型的。甚至许多程序员为了避免访问的麻烦,干脆把自己添加的成员函数和成员变量都定义成public类型。

  殊不知,这是一种规划的失败。在类的设计阶段,我们就要很清楚地知道,这个类的成员函数中哪些是这个类的接口,哪些属于这个类内部的成员函数和变量。一般的准则是接口(public成员)应在满足需求的前提下尽可能简单!

  所以不要轻易地将private/protected成员改为public成员,真正的工作应该在规划阶段完成。

  3.结束语

  所有的程序员都要经历一个从糊涂到清楚的过程,文中的错误假如你也犯了,切勿自惭。更多的错误语录,希望能在后续文章中陆续推出。

C/C++编程新手错误语录
更多内容请看C/C++技术专题 Java编程开发手册专题,或
 
 
 
上一篇《C语言中可变参数的用法》
下一篇《C++中extern “C”含义深层探索》
 
 
 
 
 
 
日版宠物情人插曲《Winding Road》歌词

日版宠物情人2017的插曲,很带节奏感,日语的,女生唱的。 最后听见是在第8集的时候女主手割伤了,然后男主用嘴帮她吸了一下,插曲就出来了。 歌手:Def...

兄弟共妻,我成了他们夜里的美食

老钟家的两个儿子很特别,就是跟其他的人不太一样,魔一般的执着。兄弟俩都到了要结婚的年龄了,不管自家老爹怎么磨破嘴皮子,兄弟俩说不娶就不娶,老父母为兄弟两操碎了心...

如何磨出破洞牛仔裤?牛仔裤怎么剪破洞?

把牛仔裤磨出有线的破洞 1、具体工具就是磨脚石,下面垫一个硬物,然后用磨脚石一直磨一直磨,到把那块磨薄了,用手撕开就好了。出来的洞啊很自然的。需要猫须的话调几...

我就是扫描下图得到了敬业福和爱国福

先来看下敬业福和爱国福 今年春节,支付宝再次推出了“五福红包”活动,表示要“把欠大家的敬业福都还给大家”。 今天该活动正式启动,和去年一样,需要收集“五福”...

冰箱异味产生的原因和臭味去除的方法

有时候我们打开冰箱就会闻到一股异味,冰箱里的这种异味是因为一些物质发出的气味的混合体,闻起来让人恶心。 产生这些异味的主要原因有以下几点。 1、很多人有这种习...

 
 
 
     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的话,对应的是同一片内存单元。 [url=http://www.wangchao.net.cn/bbsdetail_1785330.html][img]http://image.wangchao.net.cn/it/1323423858200.gif[/img][/url] 更多内容请看C/C++技术专题 java编程开发手册专题,或   规则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),仅仅意味着数组的存放地址;   规则4 数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针;很遗憾,在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。 例如: void arrayTest(char str[]) { cout << sizeof(str) << endl;   //输出指针长度     str++; //编译正确 } int main(int argc, char* argv[]) {  char str1[10] = "I Love U";  arrayTest(str1); return 0; } (5)“整形变量为32位”   整形变量是不是32位这个问题不仅与具体的CPU架构有关,而且与编译器有关。在嵌入式系统的编程中,一般整数的位数等于CPU字长,常用的嵌入式CPU芯片的字长为8、16、32,因而整形变量的长度可能是8、16、32。在未来64位平台下,整形变量的长度可达到64位。   长整形变量的长度一般为CPU字长的2倍。   在数据结构的设计中,优秀的程序员并不会这样定义数据结构(假设为WIN32平台): typedef strUCt tagTypeExample { unsigned short x; unsigned int y; }TypeExample; 他们这样定义: #define unsigned short UINT16 //16位无符号整数 #define unsigned int UINT32 //32位无符号整数 typedef struct tagTypeExample { UINT16 x; UINT32 y; }TypeExample; [url=http://www.wangchao.net.cn/bbsdetail_1785330.html][img]http://image.wangchao.net.cn/it/1323423858239.gif[/img][/url] 更多内容请看C/C++技术专题 Java编程开发手册专题,或   这样定义的数据结构非常具有通用性,假如上述32平台上的数据发送到16位平台上接收,在16位平台上仅仅需要修改UINT16、UINT32的定义: #define unsigned int UINT16 //16位无符号整数 #define unsigned long UINT32 //32位无符号整数   几乎所有的优秀软件设计文档都是这样定义数据结构的。 (6)“switch和if …else…可随意替换”   switch语句和一堆if…else…的组合虽然功能上完全一样,但是给读者的感受完全不一样。if…else…的感觉是进行条件判定,对特例进行非凡处理,在逻辑上是“非凡与一般”的关系,而switch给人的感觉是多个条件的关系是并列的,事物之间不存在非凡与一般的关系,完全“对等”。 譬如: //分别对1-10的数字进行不同的处理,用switch switch(num) { case 1: … case 2: … } //对1-10之间的数字进行非凡处理,用if if(num < 10 && num > 1) { … } else { … }   许多时候,虽然不同的代码可实现完全相同的功能,但是给读者的感觉是完全不同的。譬如无条件循环: while(1) { }   有的程序员这样写: for(;;) { }   这个语法没有确切表达代码的含义,我们从for(;;)看不出什么,只有弄明白for(;;)在C/C++语言中意味着无条件循环才明白其意。而不懂C/C++语言的读者看到while(1)也可猜到这是一个无条件循环。 (7)“免得麻烦,把类里面的成员函数都搞成public算了”   许多人编C++程序的时候,都碰到这样的情况,先前把某个成员函数定义成类的PRivate/protected函数,后来发现又要从外面调用这个函数,就轻易地将成员函数改为public类型的。甚至许多程序员为了避免访问的麻烦,干脆把自己添加的成员函数和成员变量都定义成public类型。   殊不知,这是一种规划的失败。在类的设计阶段,我们就要很清楚地知道,这个类的成员函数中哪些是这个类的接口,哪些属于这个类内部的成员函数和变量。一般的准则是接口(public成员)应在满足需求的前提下尽可能简单!   所以不要轻易地将private/protected成员改为public成员,真正的工作应该在规划阶段完成。 3.结束语   所有的程序员都要经历一个从糊涂到清楚的过程,文中的错误假如你也犯了,切勿自惭。  更多的错误语录,希望能在后续文章中陆续推出。 [url=http://www.wangchao.net.cn/bbsdetail_1785330.html][img]http://image.wangchao.net.cn/it/1323423858253.gif[/img][/url] 更多内容请看C/C++技术专题 Java编程开发手册专题,或
󰈣󰈤
 
 
 
  免责声明:本文仅代表作者个人观点,与王朝网络无关。王朝网络登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
赏心悦目的模特儿(9)
赏心悦目的模特儿(8)
赏心悦目的模特儿(7)
赏心悦目的模特儿(6)
周六一日游--绿野翠蜂场(一)
骆驼峰
下一站上环
杂乱的几张Danang
 
>>返回首页<<
 
 
 为你推荐
 
 
 
 转载本文
 UBB代码 HTML代码
复制到剪贴板...
 
 热帖排行
 
 
 
 
©2005- 王朝网络 版权所有