创造高质量的个人代码风格
太多人会写代码,却只有极少的程序员可以将代码写出美感,你想让自己的代码成为高质量代码吗?下面这些建议一定可以帮到你。
以下是高质量代码需遵循的建议,下方有优秀代码示例。
一、文件结构
【建议1】为了防止头文件被重复引用,应当用ifndef/define/endif结构产生预处理块。
【建议2】用#include <filename.h>格式来引用标准库的头文件(编译器从标准库目录开始搜索)。
【建议3】用#include “filename.h”格式来引用非标准库的头文件(编译器先从用户的工作目录开始搜索,搜不到再到标准库里找,为节省时间引用库函数用<>格式)。
【建议4】头文件中只存放“声明”而不存放“定义”。
二、程序的版式
· 空行
【建议1】每个函数构建完成后在下方都要加一行空行,来与其他语句块分隔开。
【建议2】在一个函数体内,逻辑上密切相连的语句间不加空行,与其他语句间要用一行空格加以分隔。
【建议3】用空格将声明部分和程序其他部分区分开。
· 代码行
【建议1】一行代码只做一件事,如只定义一个变量,或只写一条语句。这样代码易于阅读和写注释。
【建议2】if、else、for、while、do等语句独自占一行,执行语句不得紧跟其后。不论执行语句有多少都要加{ }。这样可以防止书写失误。
【建议3】尽可能在定义变量的同时初始化变量。
· 代码行内的空格
【建议1】函数名紧跟左括号 ‘(’,不要留空格;而if、for、while等关键字之后应留一个空格再跟左括号,这样便于区别函数和关键字。
【建议2】逗号 ‘,’之后要留一个空格,分号 ‘;不是一行的结束符号时,其后要留一个空格。
【建议3】赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符,如“=”、“+=”“>=”、“<=”、“+”、“*”、“%”、“&&”、“||”、“<<”,“^”等二元操作符的前后应当加空格。
【建议4】一元操作符如“!”、“~”、“++”、“- -”、“&”(地址运算符)等前后不加空格。
· 对齐
【建议1】程序的分界符 ‘{’ 和 ‘}’ 应独自占一行并且位于同一列,同时与引用
它们的语句左对齐。
【建议2】{ }之内的代码块在 ‘{’ 右边数格处左对齐。
· 长行拆分
【建议1】每一行代码行不要太长。
【建议2】长表达式要在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要进行适当的缩进,使排版整齐,语句可读。
//变量千万不要这样定义,这样写只是为了举例
if ((very_very_long_sentence1>= very_very_long_sentence2)
&&(very_very_long_sentence3<= very_very_long_sentence4)
&&(very_very_long_sentence5==very_very_long_sentence6))
//操作符放在新行之首,同时注意对齐
for (very_very_very_very_long_sentence=0;
very_very_very_very_long_sentence<10;
very_very_very_very_long_sentence++)
· 修饰符的位置
【建议1】修饰符 * 和 & 应紧靠变量名
//y容易被误解为指针
int* x, y;
//此处y不易被误解
int *x, y;
//更好的格式应为分行定义
int *x;
int y;
· 注释
【建议1】注释是对代码的“提示”,要精简、准确,不要花里胡哨。
【建议2】对复杂或有特殊意义的代码才进行注释,简单语句不注释
【建议3】边写代码边注释,修改代码同时修改相应的注释,无用注释要删除。
下为良好风格的代码:
//一行只定义一个变量并尽量初始化
int width = 0;
int depth = 0;
int height = 0;
//一行只写一个语句,操作符前后各加一个空格
x = a + b;
y = c + d;
z = e + f;
//for与‘(’间留一个空格,‘;’后空一格,操作符前后都空一格
//‘{’和‘}’独占一行且位于同一列,与for左对齐
for (i = 0; i < 10; i++)
{
do_something();
}
//空一行,与其他语句隔开,一个模块为一部分
other();
三、命名规则
· 命名规则
【规则1】标识符应直观且可拼读,望文知意。
【规则2】命名风格保持一致。若用“大小写”分隔方式,如AddNumber,就全用该方式;若用“小写加下划线”的方式,如add_number,就只用这种方式,不要将两种方式混用。
【规则3】程序不要出现仅靠大小写区分的相似的标识符
int x, X; //容易混淆,不要这样写
· 命名惯例
函数名首字母大写其余小写
int Add(int x);
#define定义的常量字母全大写
#define MAX 100
静态变量加前缀s_(表示static)
static int s_name; //静态变量
不得不用全局变量,全局变量加前缀g_(表示global)
int g_name; //全局变量
四、表达式和基本语句
· 括号()的使用
若代码行中的运算符较多,要用括号()确定表达式的操作符,防止产生歧义。
· 浮点型变量的比较
浮点型与0或浮点数的比较不能使用“==”或“!=”,应设法转换为“>=”或“<=”的形式。(因为精度缺失的原因)
#include<stdio.h> //使用以下两个精度,需要包含改头文件。
DBL_EPSILON //double最小精度
FLT_EPSILON //float最小精度
float x = 0;
if (x == 1.0) //错误的比较
//应该转化为
if ((x - 1.0) > -FLT_EPSILON && (x - 1.0) < FLT_EPSILON)
//或
if (fabs(x - 1.0) < FLT_EPSILON)
注:fabs是C语言函数库中求绝对值的函数,头文件#include <math.h>。
· 指针比较
指针变量是与NULL(空指针)比较,而不是和0比。
· for循环
不要在for循环内修改循环变量,应在for后()内修改,防止for循环失去控制。
· switch语句
【建议1】每个case语句的结尾不要忘了加break,否则将导致多个分支重叠。(除非有意为之)
【建议2】不管用不用,都最好在代码块的最后加一个default分支,利于以后的修改。
五、函数设计
· 参数规则
如果参数是指针,且仅输入不改值,则应在类型前加const,以防该指针在函数体内被意外修改。
//源字符串不应被修改,用const修饰
char * strcpy(char *destination, const char *source);
· 设计函数的建议
每个函数的功能要单一,不要让一个函数实现多个功能;规模要小,尽量控制在50行代码以内。
· 使用断言
char *clone_string( const char *source )
{
char *result;
//使用断言,防止出现使用空指针的情况
assert( source != NULL );
......
}
断言的使用可排除不应发生的非法情况,让程序更稳定。
六、内存管理
· 内存分配
内存分配,极易出错,遵循建议,干掉小错误!
【建议1】用malloc申请完内存后,应立即判断是否申请成功,检查指针是否为空指针
//自定义函数中用断言
assert(p != NULL);
//main函数体中用
if (p == NULL)
//或
if (p != NULL) //来防错
【建议2】定义数组和申请动态内存是需要赋初值,防止使用了未初始化的内存。
【建议3】当心数组和指针的下标是否发生“多1”或“少1”的操作,避免越界访问。
【建议4】动态内存分配后一定要记得在后面用free将它释放,且内存释放后要立刻将指针设置为空指针,防止产生“野指针”。
int* p = (int*)malloc(40);
if (p == NULL) //判断内存是否申请成功
{
printf("%s\n", strerror(errno));
return 0;
}
free(p); //内存释放
p = NULL; //置为空指针
申请的动态内存不会自动释放,自己一定不要忘记手动释放,否则动态内存申请的太多而未释放可能导致程序崩溃。
完结
C语言细微的规则还有许多,有的一般的学习者都可避免,有的则太过细小,上面的内容已涉及绝大多数值得注意和学习的规则与建议,相信只要读者将它们完全融会贯通、内化到自己的代码风格中后,一个属于你自己的优秀代码风格诞生啦。别的程序员见到直接顶礼膜拜,面试官直接双手奉上好offer。
继续加油呀,与君共勉!