在看完《编程修养》【From:陈皓专栏http://blog.youkuaiyun.com/haoel/article/details/2872】之后,觉得非常有必要把书里面提到的而自己平时忽略的地方给拾起来了,不能再写一些让别人看不懂的代码了,需要在以后的写代码过程中作为手边的“警钟”,时刻注意提高“修养”。
越是坏的东西,发展就越快。“千里之堤,毁于蚁穴”,对于自己不好的一面,要尽快改掉,避免拖拉。
下面是阅读此书之笔记。
——————————————————————————————————————————
问题:什么是优秀的程序员?
问题:程序员应该具有什么样的素质?
此书作者的观点:
1.有专研精神,勤学善问、举一反三。
2.积极向上的态度,有创造性思维。
3.与人积极交流沟通的能力,有团队精神。
4.谦虚谨慎,戒骄戒燥。
5.写出的代码质量高。包括:代码的稳定、易读、规范、易维护、专业。
程序员写出的程序作品应该是一件艺术品。
上面这五点,自己在平时的学习和工作中之中,应该反思,那些地方需要改进的,哪些是需要提高的。
——————————————————————————————————————————
总结了在C/C++语言进行程序写作的三十二个“修养”
1.版权和版本
文件头应有这样的注释:
/************************************************************************
** file name:free.c
** Author: hgj
** Date: 2013/1/11
**
** Description: FIRST_DEMO ------malloc calloc realloc和free函数用法练习
** SECOND_DEMO ------free函数练习
** THIRD_DEMO ------perror函数练习
** FORTH_DEMO ------free(p)之后产生的野指针练习
** Version: 1.0
** Modify:
/************************************************************************/
而对于函数来说,应该有这样的注释:/************************************************************************
** Function Name: main
** Para: void
** Description:
** Return: 成功: 失败:
** Author:
** Note:
/************************************************************************/
这样的描述可以让阅读者对一个文件,函数有一个总体上的认识,对代码的易读性和可维护性有很大的好处,START2.缩进、空格、换行、空行、对齐
缩进:不成文的规矩,一个缩进一般是一个tab键或者4个空格(最好用tab键)。
空格:语句中要在各个操作符之间加空格,函数调用时,要在各个参数之间加空格。
换行:不要把语句都写在一行上,有时候参数多的时候,也要换行,条件语句太多时,也要换行(操作符放在新行之首)。
空行:在不同的程序块之间加上空行。
对齐:用tab键对齐程序中对一些变量的声明或注释。
3.程序注释
包括:文件注释,函数注释,变量的注释,算法的注释,功能块的程序注释
尽量使用块注释(/**/)和宏注释(#if 0 #endif)而不用行注释(//),一些老的C编译器不支持行注释,对程序的移植性不利。
注释应该准确,不应具有二义性。
程序代码段落比较长,在段落结束处加上注释,便于阅读。
4.函数的【IN】【OUT】参数
对于传进来的参数,必须检查其合法性,结合assert宏使用。
对于传出来的参数,在函数外部也要检查其合法性。
这样的检查会浪费一点时间,但是避免了“非法操作”或“Core Dump”的系统级错误。
5.对系统调用的返回进地判断
接着上一条,对于一些系统调用,比如fopen ,malloc,socket等,而要对其返回的东西作出判断
6.if语句对出错的处理
先判断合法的情况,再判断不合法的情况。 “正常处理”代码很长的话,最好不要用else
先判断不合法的情况,然后判断合法的情况。 突出错误情况,在别人使用时,会更下意识的避免。
if (str==NULL)
{
perror("malloc");
abort();
}
else
{
strcpy(str,"hello");
printf("String is %s\n",str);
free(str);
}
7.头文件中的#ifndef
在头文件上千万不要忽略了#ifndef 标识符 ,最好用“文件名变成大写,点换成下划线”
为了防止头文件被重复引用,需要加上#ifndef/#define/#endif结构产生的预处理块。
/*为了防止头文件被重复引用,此结构具有可移植性*/
#ifndef __HEADFILE_H_
#define __HEADFILE_H_
#endif
#include <headfile.h> /*引用标准库头文件,编译器将从标准库目录开始搜索*/
#include "heaefile.h" /*引用非标准库头文件,编译器将从用户的工作目录开始搜索*/
8.在堆上分配内存
stack一般是静态分配内存,heap一般是动态分配内存。
由heap上分配的内存一定要自己释放,否则会造成“内存泄露”(Memory Leak)
Rational有一个工具叫Purify,可以很好的帮助你检查程序中Memory Leak.
9.变量的初始化
变量一定要初始化再使用。对于malloc分配的内存进行memset清零操作,对于一些栈上分配的struct或数组进行初始化。
char **ptr; /*一个字符串数组*/
ptr = (char **) malloc( 50 );
if (NULL == ptr)
{
exit(0);
}
memset( ptr, 0, 50*sizeof(char*) ); /*让数组中的指针都都指向NULL*/
对于全局变量和静态变量,一定要声明时进行初始化。
Links *plink = NULL;
10.h和c文件的使用
H文件是declare,C文件是define。H文件中一般是变量,宏定义,枚举,结构和函数接口的声明,就像一个接口说明文件一样,而C文件则是实现细节。
如果在H文件中写上文件的实现,你还得在makefile中把头文件的依赖关系也加上,这样使makefile不规范。
(如果是VC的话,对于其模板函数,在VC中只有把实现和声明写在一个文件中,因为VC不支持extern关键字)
注意:带初始化的全局变量不要放在H文件中。
书中在于处理错误信息的结构这块,要好好的去理解,看到这里再翻开书本看一下。
11.出错信息的处理
定我自己的错误信息处理结构。
12.常用函数和循环语句中的被计算量
把循环体中不变的东西挪到循环外边
对于常用函数中不变的量声明为static,会省去内存分配的开销,执行效率也会很好。
13.函数名和变量名命名
要求见名知意,有统一风格,加模块的前缀或后缀。
14.函数的传值和传指针
传值只是内存拷贝
15.修改别人程序的修养
这种 方法在软件维护时使用
以“注释--添加”方式修改别人的程序,要好于直接删除别人的程序
/*-----commented by XXX 2013/1/11--------
** char *p=(char *)malloc(10);
** memset(p,0,10);
*-----------------------------------------/
/*-----Add by XXX 2013/1/11_____________________*/
char *p = (char *)calloc( 10, sizeof char );
/*----------------------------------------------*/
16.把相同和近乎相同的代码形成函数或宏千万不要让同一份代码或功能相似的代码在多个地方存在,如果功能一变,就得全部修改,最好形成函数或宏,做到“一改全改”。
17.表达式中的括号
如果一个复杂的表达式,不是很清楚其中各个操作符的优先级,即使清楚,也最好加上括号下次阅读代码的时候会很快的知道其逻辑关系。
GetUserAge( &(UserInfo ->age) );
->的优先级最高,但是加上一个括号,很容易的让人知道是什么意思。
18.函数参数中的const
对于函数中的指针参数,如果用const修饰,则会很容易的知道这个参数是[in].利于程序的维护。
在C++中const要严格的多。
19.函数的参数个数(多了请用结构)
用结构struct来传递参数,就可以不用管参数的顺序。
20.函数的返回类型,不要省略。
即使函数的返回类型是void,也在内部加上return语句,有助于代码的编译。
21.goto语句的使用
goto statment is harmful
不建议使用,除非下面这种情况,请查看书本上的例子。
22.宏的使用
特别是当宏有参数和时候,注意其副作用。
宏执行很快(因为没有函数调用的开销,)但宏会让源代码膨胀,使目标文件尺寸变大。
23.static的使用。
static声明的变量只会在函数第一次被调用时才会被分配或初始化,以后每次进入函数,都不会再分配了,而直接使用上一次的值。
static最大的作用在于访问控制,这样的特性有助于数据和程序的保密。
24.函数代码中的尺寸
函数的功能尽可能的单一,不把要多个功能在一个函数中实现。
这样虽然会花费一定的开销,但是这样易于软件的维护。
25.typedef的使用
typedef这个关键字很重要,涉及到跨平台。在结构和函数指针时,也最好用typedef,这样有利于程序的易读和维护。
26.为常量声明宏
不要在程序中出现“硬编码”,为它们申请一个宏吧
27.不要为宏定义加上分号
#define LINE "================"
#define PRINT_LINE printf(LINE)
#define PRINT_NLINE(n) while (n-- >0) {PRINT_LINE;}
/*都不要在最后加上分号,当我们在程序中使用时,为之加上分号*/
main()
{
char *p=NULL;
PRINT_LINE;
}
28.|| 和 &&的语句执行顺序
条件语句中,并非所有的语句都会执行。当你的语句非常多时,,这点要尤其注意。
29.尽量要用for而不是用while循环
30.请sizeof 类型而不是变量名
/*分配一个有20个字符串,每个字符串长100的内存*/
char **p;
p=(char *)calloc(20,sizeof (char*));
for (i=0;i<20;i++)
{
p[i]=(char *)calloc(100,sizeof(char));
}
/*分配完毕*/
31.不要忽略warning
warning信息不可忽视
32.书写Debug版和Release版本的程序
看完之后,发现这些总结的32点经验,其中的一些的确是平时忽略了,现在看完了,并不代表全记住了,以后还得继续多看,多写,多注意,既然看到了这些,在以后书写代码的过程中就得以这上面提到的为标准。否则这些看了也没有用,关键在于action,action.