前言
世界上有两种程序员:一种是草草写完代码然后化身苦逼程序猿苦苦寻找bug
;另一种是上手就写出高质量的代码化身bug终结者。优秀的程序员往往将bug扼杀在萌芽中,很明显这是“另一种”程序猿,那么我们应该怎样写出一手高质量的优秀代码呢?
一、优秀的代码
什么是优秀的代码?优秀的代码具有以下特点:
- 代码运行正常
- bug很少
- 效率高
- 可读性高
- 可维护性高
- 注释清晰
- 文档齐全
二、常见coding技巧
当然了,想要写出以上优秀的代码,需要我们在编码时刻意的去使用一些编码技巧,例如一些常见的coding
技巧:
- 使用assert
- 尽量使用const
- 养成良好的编码风格
- 添加必要的注释
- 避免编码的陷阱
现在大家可能还体会不到这些coding技巧带来的实际意义,下面就以实例向大家演示:
三、模拟实现库函数:strcpy
我们已知库函数strcpy
的作用是将含有'\0'
结束符的字符串复制到另一个地址空间。根据它的功能,我们利用指针偏移模拟复刻出以下代码:
虽然上述代码也可以模拟实现出strcpy
函数的功能,但是这是一种非常不好的代码风格。我们应该怎样对其优化呢?
1、优化一:字符复制和‘\0’复制的整合
初代代码,我们将内容复制和最后‘\0’的复制功能分离,对此我们可以将二者功能整合,使代码更巧妙紧凑。
2、优化二:使用assert
在拷贝函数中我们对指针进行了解引用等相关操作,但是如果在传参过程中不小心传入了一个空指针呢?我们知道空指针是不能进行这些操作的,一但传入空指针该程序就会崩掉,并且我们不知所以然,还要通过调试一步一步的去定位错误。为了能够很好的预防和避免以上问题,我们可以在程序中添加assert函数:
这里我们假设无意中传入一个空指针,看看会出现什么效果:
屏幕上输出:Assertion failed:src
-断言错误: src
,我们可以根据提示,追根溯源一步步锁定错误。
同样都是判断,为什么不使用if语句呢?
if
语句在Debug
版本和Release
版本都会被执行,而assert
仅在Debug
版本中执行,在Release版本中会被优化掉。综上来看,assert是对程序员非常友好的一个库函数。
3、优化三:const修饰
观察库函数的特征,函数中存在一个const修饰的指针变量,这里的const
又有什么样的作用呢?下面我们通过以下三种代码的可执行情况来分析:
const修饰指针变量的时候:
- const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改 变。但是指针变量本身的内容可变。
- const如果放在*的右边,修饰的是指针变量本身,保证了指针变量的内容不能修改,但是指 针指向的内容,可以通过指针改变。
结合const修饰指针变量的作用,我们对原始数据的指针变量使用const修饰,意味着原始数据不可修改,这里起到了保护原始数据的作用。
例如:在拷贝数据时我们不小心将*dest++=*src++误写成*src++=*dest++,如果不使用const修饰src,当程序报错后还需一步一步调试从而定位错误,如果使用了const修饰src,我们可以很快在报错信息中定位错误,提高效率。
4、优化四:添加返回值
字符串拷贝函数返回的是目标空间的起始地址。
5、优化五:添加注释
虽然注释并不参与编译,但是在开发中注释也具有十分重要的作用。
- 有助于理解
- 帮助修补程序或快速修复
- 有助于加快开发过程
- 有助于提高协作效率
//模拟strcpy函数--注释 //功能: //char* my_strcpy(char* dest, const char* src)-将字符串src复制到另一个字符串dest上 //参数: //char* dest - 目标字符串 //const char* src - 要在“dest”上复制的字符串 //返回值: //目标字符串的首元素地址
6、最终代码
//模拟strcpy函数--注释 //功能: //char* my_strcpy(char* dest, const char* src)-将字符串src复制到另一个字符串dest上 //参数: //char* dest - 目标字符串 //const char* src - 要在“dest”上复制的字符串 //返回值: //目标字符串的首元素地址 #include<assert.h> char* my_strcpy(char* dest, const char* src) { assert(dest); assert(src); char* ret = dest;//用来定位首元素地址 while (*dest++ = *src++)//既拷贝了内容又能很好的停下 { ; } return ret; }
7、练习:模拟实现strlen函数
仿照以上优化思路,我们也可以类似的对库函数strlen
进行模拟实现。
//模拟strlen函数--注释 //功能:统计字符串长度,不包括‘\0’ //参数:const char* str-被统计字符串地址 //返回值:字符串长度,不包括‘\0’ #include<assert.h> int my_strlen(const char* str) { assert(str); int count = 0; while (*str) { count++; str++; } return count; }
总结
纸上得来终觉浅,绝知此事要躬行。想要写出优秀的代码,需要我们在编码时刻意的对代码进行研判,学习借鉴好的代码风格,时常总结,积累经验。在这里特别推荐两本可以提高代码质量的书籍:《高质量的C-C++编程》《C陷阱与缺陷》或许在这里面可以找到你想要的更多答案!