科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道应用软件C/C++编程新手错误分析

C/C++编程新手错误分析

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文列出了编程新手在项目开发中常见的问题,并加以分析解决

作者:宋宝华 来源:PConline  2007年9月15日

关键字: C++ 编程 错误 软件

  • 评论
  • 分享微博
  • 分享邮件

(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;

tr++; //编译出错,提示str不是左值 

Str++; //编译正确

规则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;

}

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章