高质量编程规范PPT参考课件_第1页
高质量编程规范PPT参考课件_第2页
高质量编程规范PPT参考课件_第3页
高质量编程规范PPT参考课件_第4页
高质量编程规范PPT参考课件_第5页
已阅读5页,还剩57页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、上章回顾上章回顾哈希函数的构造方法有那些哈希表中处理冲突的方法有那些高质量编程规范高质量编程规范第八章第八章预习检查预习检查c语言要经历哪几个编译过程如何申请链表单元,及释放链表单元实现单链表插入的基本语法简述一下快速排序基本理论要点课程目标课程目标本章概述本章概述阐述如何进行高质量的编程,以及注意事项本章目标本章目标了解高质量编程注意的方方面面从代码风格,算法,方便调试,性能等。重点重点内存分配与释放,悬挂指针本章结构本章结构程序员的态度程序员的态度高质量编程规范高质量编程规范微观上高质量微观上高质量宏观上高质量宏观上高质量8.1 程序员的态度程序员的态度程序员的弱点不太愿意测试自己的代码

2、不愿意review团队队员的代码程序员重点保证自己的代码没有 bug 来 8.1 程序员的态度程序员的态度程序员自身可以在程序生成的流程 详细设计 编写代码单元测试 功能测试 代码 review 8.1.1 编码的风格编码的风格版权和版本的申明头文件的结构定义文件的结构头文件的作用目录结构命名规则注释规则/* copyright (c) 2001,上海贝尔有限公司网络应用事业部上海贝尔有限公司网络应用事业部* all rights reserved.* * 文件名称:文件名称:filename.h* 文件标识:文件标识:见配置管理计划书见配置管理计划书* 摘摘 要:要:简要描述本文件的内容简要

3、描述本文件的内容* * 当前版本:当前版本:1.1* 作作 者:者:输入作者(或修改者)名字输入作者(或修改者)名字* 完成日期:完成日期:2001年年7月月20日日* 取代版本:取代版本:1.0 * 原作者原作者 :输入原作者(或修改者)名字输入原作者(或修改者)名字* 完成日期:完成日期:2001年年5月月10日日8.1.1.1 版权和版本的申明版权和版本的申明版权和版本的声明位于头文件和定义文件的开头,主要内容有:(1)版权信息。(2)文件名称,标识符,摘要。(3)当前版本号,作者/修改者,完成日期。(4)版本历史信息。范例8.1.1.2头文件的结构头文件的结构头文件由三部分内容组成:头

4、文件开头处的版权和版本声明。预处理块。函数和类结构声明等。范例为了防止头文件被重复引用,应当用ifndef/define/endif结构产生预处理块。用 #include 格式来引用标准库的头文件(编译器将从标准库目录开始搜索)。用 #include “filename.h” 格式来引用非标准库的头文件(编译器将从用户的工作目录开始搜索)。头文件中只存放“声明”而不存放“定义”不提倡使用全局变量,尽量不要在头文件中出现象extern int value 这类声明。8.1.1.3定义文件的结构定义文件的结构定义文件有三部分内容:定义文件开头处的版权和版本声明对一些头文件的引用程序的实现体(包括数

5、据和代码)范例/ 版权和版本声明版权和版本声明#include “graphics.h” / 引用头文件引用头文件/ 全局函数的实现体全局函数的实现体void function1()8.1.1.4 头文件的作用头文件的作用通过头文件来调用库功能头文件能加强类型安全检查8.1.1.5 目录结构目录结构特点:便于维护通常应将头文件和定义文件分别保存于不同的目录加强信息隐藏:如果某些头文件是私有的,它不会被用户的程序直接引用,则没有必要公开其“声明”范例: network 工程建立三个目录 source:存放工程源文件,如:server.c client.c include:存放工程头文件,如:se

6、rver.h client.h lib:存放工程库文件,如:tipr.so stdio.so8.1.1.6 命名规则命名规则主要思想:在变量和函数名中加入前缀以增进人们对程序的理解具体规则:标识符应当直观且可以拼读,可望文知意,不必进行“解码”。标识符的长度应当符合“min-length & max-information”原则命名规则尽量与所采用的操作系统或开发工具的风格保持一致程序中不要出现仅靠大小写区分的相似的标识符程序中不要出现标识符完全相同的局部变量和全局变量变量的名字应当使用“名词”或者“形容词名词”用正确的反义词组命名具有互斥意义的变量或相反动作的函数等8.1.2 程序的

7、版式程序的版式空行代码行代码行内的空格代码对齐长行拆分修饰符的位置注释8.1.2.1 空行空行空行起着分隔程序段落的作用。空行得体(不过多也不过少)将使程序的布局更加清晰。空行不会浪费内存空行规则每个函数定义结束之后都要加空行在一个函数体内,逻揖上密切相关的语句之间不加空行,其它地方应加空行分隔。8.1.2.2 代码行规则代码行规则一行代码只做一件事情如只定义一个变量,或只写一条语句。这样的代码容易阅读,并且方便于写注释。if、for、while、do等语句自占一行,执行语句不得紧跟其后。不论执行语句有多少都要加。尽可能在定义变量的同时初始化该变量(就近原则)8.1.2.3 代码行内的空格代码

8、行内的空格 关键字之后要留空格函数名之后不要留空格,紧跟左括号(,以与关键字区别(向后紧跟,)、,、;向前紧跟,紧跟处不留空格,之后要留空格二元操作符的前后应当加空格。一元操作符前后不加空格。象“”、“.”、“-”这类操作符前后不加空格。8.1.2.4 对齐和拆分规则对齐和拆分规则对齐规则程序的分界符和应独占一行并且位于同一列,同时与引用它们的语句左对齐 之内的代码块在右边数格处左对齐。长行拆分规则代码行最大长度宜控制在70至80个字符以内长表达式要在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要进行适当的缩进,使排版整齐,语句可读8.1.2.5 长行拆分规则

9、长行拆分规则 代码行最大长度宜控制在70至80个字符以内 长表达式要在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符) 例:if (very_longer_variable1 = very_longer_variable12)& (very_longer_variable3 = very_longer_variable14)& (very_longer_variable5 = b & c d & c + f = g + h ; 不要有多用途的复合表达式 d = (a = b + c) + r ; 不要把程序中的复合表达式与“真正的数学表达式”混淆

10、 if (a b c) 与 if (ab) & (b=”或“=-epsinon) & (x=epsinon) 其中epsinon是允许的误差(即精度)。 8.2.1.3 if语句语句指针变量与零值比较指针变量与零值比较 指针变量用“=”或“!=”与null比较 例子:与零值比较的标准与零值比较的标准if语句如下:语句如下:if (p = null)/ p与与null显式比较,强调显式比较,强调p是指针变量是指针变量if (p != null)不要写成不要写成if (p = 0) / 容易让人误解容易让人误解p是整型变量是整型变量if (p != 0) 或者或者 if (p)/

11、容易让人误解容易让人误解p是布尔变量是布尔变量if (!p)8.2.1.4 使用使用const提高函数的健壮性提高函数的健壮性 const 用法:定义常量 修饰函数的参数 修饰函数的返回值 修饰函数的定义体 8.2.1.4.1 用用const修饰函数的参数修饰函数的参数const只能修饰输入参数 特点如果输入参数采用“指针传递”,那么加const修饰可以防止意外地改动该指针,起到保护作用 例:void stringcopy(char *strdestination, const char *strsource); 如果输入参数采用“引用传递 ”, 可以避免修改参数值的值传递void func(

12、const a &a) 8.2.1.4.2 用用const修饰函数的返回值修饰函数的返回值 如果给以“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针)内容不能被修改例如函数const char * getstring(void);如下语句将出现编译错误:char *str = getstring();正确的用法是const char *str = getstring();8.3.1 防止内存泄漏防止内存泄漏 内存分配方式 malloc/free 的使用要点 常见的内存错误及其对策 引用与指针的比较 指针与数组的对比 指针参数是如何传递内存的动态内存自动释放 杜绝“野

13、指针” 8.3.1.1内存分配方式内存分配方式 内存分配方式有三种:从静态存储区域分配 在栈上创建 从堆上分配,亦称动态内存分配 malloc或new free或delete 8.3.1.2 malloc/free 的使用要点的使用要点 malloc语法:void * malloc(size_t size); 作用:申请一块长度为length的整数类型的内存 例子:int *p = (int *) malloc(sizeof(int) * length) free语法:void free( void * memblock ) 作用:释放内存 例子:free(p)如果p是null指针,那么fre

14、e对p无论操作多少次都不会出问题如果p不是null指针,那么free对p连续操作两次就会导致程序运行错误。8.3.1.3 常见的内存错误及其对策常见的内存错误及其对策 常见的内存错误 内存分配未成功,却使用了它 内存分配虽然成功,但是尚未初始化就引用它 内存分配成功并且已经初始化,但操作越过了内存的边界 忘记了释放内存,造成内存泄露 释放了内存却继续使用它 8.3.1.3 常见的内存错误及其对策常见的内存错误及其对策 内存管理的规则 用malloc之后,应该立即检查指针值是否为null。防止使用指针值为null的内存。不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。避免数组

15、或指针的下标越界,特别要当心发生“多1”或者“少1”操作。动态内存的申请与释放必须配对,防止内存泄漏。用free释放了内存之后,立即将指针设置为null,防止产生“野指针”。8.3.1.5 指针与数组的对比指针与数组的对比 差别数组:要么在静态存储区被创建(如全局数组),要么在栈上被创建 数组名对应着(而不是指向)一块内存其地址与容量在生命期内保持不变只有数组的内容可以改变 指针:随时指向任意类型的内存块 动态生存在数据堆8.3.1.5 指针与数组的对比指针与数组的对比 差别内存的容量大小例:1例2char a = hello world; char *p = a; sizeof(a) ?/

16、12字节字节 sizeof(p) ?/ 4字节字节 void func(char a100) sizeof(a) ? / 4字节而不是字节而不是100字节字节 8.3.1.5 指针与数组的对比指针与数组的对比 动态内存会自动释放 不会自动释放例:指针应该注意的特性指针消亡了,并不表示它所指的内存会被自动释放。内存被释放了,并不表示指针会消亡或者成了null指针。void func(void) char *p = (char *) malloc(100); / 动态内存会自动释放吗?动态内存会自动释放吗? 8.3.1.6 指针参数是如何传递内存的指针参数是如何传递内存的*如果函数的参数是一个指针

17、,不要指望用该指针去申请动态内存如果函数的参数是一个指针,不要指望用该指针去申请动态内存 void getmemory(char *p, int num) p = (char *)malloc(sizeof(char) * num); void test(void) char *str = null; getmemory(str, 100); / str 仍然为仍然为 null strcpy(str, hello);/ 运行错误运行错误 8.3.1.6 指针参数是如何传递内存的指针参数是如何传递内存的*如果函数的参数是一个指针,不要指望用该指针去申请动态内存如果函数的参数是一个指针,不要指望用

18、该指针去申请动态内存 void getmemory2(char *p, int num) *p = (char *)malloc(sizeof(char) * num); void test(void) char *str = null; getmemory(&str, 100); / str 仍然为仍然为 null strcpy(str, hello);/ 运行错误运行错误 8.3.1.6 指针参数是如何传递内存的指针参数是如何传递内存的* * * * 不要用不要用returnreturn语句返回指向语句返回指向“栈内存栈内存”的指针的指针 char *getstring(void)

19、 char p = hello world; return p; / 编译器将提出警告编译器将提出警告 void test4(void) char *str = null; str = getstring(); / str 的内容是垃圾的内容是垃圾 printf(“%sn”,str ); 8.3.1.7动态内存自动释放动态内存自动释放 free函数特点释放指针所指的内存没有销毁指针,故指针地址仍然不变(非null)例: char *p = (char *) malloc(100);strcpy(p, “hello”);free(p); / p 所指的内存被释放,但是所指的内存被释放,但是p所指

20、的地址仍然不变所指的地址仍然不变if(p != null) strcpy(p, “world”);/ 出错出错 没有起到没有起到防错作用防错作用8.3.1.8 杜绝杜绝“野指针野指针” 什么是“野指针”不是null指针是指向“垃圾”内存的指针 if(p!=null)不能起到作用野指针的成因指针变量没有被初始化 指针初始化:char *p = null;char *str = (char *) malloc(100);指针p被free或者delete之后,没有置为null 8.3.2 编程的优化编程的优化为什么需要常量const与#define的比较常量定义规则循环语句的效率for语句的循环控制

21、变量8.3.2.1 为什么用常量为什么用常量常量是一种标识符,它的值在运行期间恒定不变。用 #define来定义常量(称为宏常量),还可以用const来定义常量为什么要常量程序的可读性在程序的很多地方输入同样的数字或字符串,难保不发生书写错误。如果要修改数字或字符串,则会在很多地方改动,既麻烦又容易出错。尽量使用含义直观的常量来表示那些将在程序中多次出现的数字或字符串。例如:#define max 100/* c语言的宏常量 */ const int max = 100;/ c 语言的const常量const float pi = 3.14159;/ c 语言的const常量8.3.2.2 c

22、onst 与与 #define的比较的比较两种区别比较const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。常量定义规则需要对外公开的常量放在头文件中,不需要对外公开的常量放在定义文件的头部为便于管理,可以把不同模块的常量集中存放在一个公共的头文件中。如果某一常量与其它常量密切相关,应在定义中包含这种关系,而不应给出一些孤立的值。例如:const float radius = 100;const float diameter = radius * 2;

23、8.3.2.3循环语句的效率循环语句的效率在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的循环放在最外层,以减少cpu跨切循环层的次数。如果循环体内存在逻辑判断,并且循环次数很大,宜将逻辑判断移到循环体的外面。for (row=0; row100; row+)for ( col=0; col5; col+ )sum = sum + arowcol;if (condition) for (i=0; in; i+) dosomething();else for (i=0; in; i+) dootherthing();8.3.2.4 for语句的循环控制变量语句的循环控制变量循环控制变

24、量规则不可在for 循环体内修改循环变量,防止for 循环失去控制 建议for语句的循环控制变量的取值采用“半开半闭区间”写法 例子:半开半闭区间 闭区间 for (x=0; xn; x+) for (x=0; x=n; x+) ;8.3.2.5 pragma预处理预处理其格式一般为: #pragma para 其中para 为参数,下面来看一些常用的参数。 #pragma message编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为:#pragma message(“消息文本”) #pragma once只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,这条指令实际上在vc6中就已经有了,但是考虑到兼容性并没有太多的使用它。pragma comment(.) 该指令将一个注释记录放入一个对象文件或可执行文件中。 常用的lib关键字,可以帮我们连入一个库文件。8.3.2.5 pragma预处理预处理#pragma pack() 对

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论