如何写出高质量的C代码?快来学习这些coding技巧

简介: 如何写出高质量的C代码?快来学习这些coding技巧

前言

世界上有两种程序员:一种是草草写完代码然后化身苦逼程序猿苦苦寻找bug;另一种是上手就写出高质量的代码化身bug终结者。优秀的程序员往往将bug扼杀在萌芽中,很明显这是“另一种”程序猿,那么我们应该怎样写出一手高质量的优秀代码呢?

一、优秀的代码

什么是优秀的代码?优秀的代码具有以下特点:

  1. 代码运行正常
  2. bug很少
  3. 效率高
  4. 可读性高
  5. 可维护性高
  6. 注释清晰
  7. 文档齐全

二、常见coding技巧

当然了,想要写出以上优秀的代码,需要我们在编码时刻意的去使用一些编码技巧,例如一些常见的coding技巧:

  1. 使用assert
  2. 尽量使用const
  3. 养成良好的编码风格
  4. 添加必要的注释
  5. 避免编码的陷阱

现在大家可能还体会不到这些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修饰指针变量的时候:

  1. const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改 变。但是指针变量本身的内容可变。
  2. const如果放在*的右边,修饰的是指针变量本身,保证了指针变量的内容不能修改,但是指 针指向的内容,可以通过指针改变。

结合const修饰指针变量的作用,我们对原始数据的指针变量使用const修饰,意味着原始数据不可修改,这里起到了保护原始数据的作用。

例如:在拷贝数据时我们不小心将*dest++=*src++误写成*src++=*dest++,如果不使用const修饰src,当程序报错后还需一步一步调试从而定位错误,如果使用了const修饰src,我们可以很快在报错信息中定位错误,提高效率。

4、优化四:添加返回值

字符串拷贝函数返回的是目标空间的起始地址。

5、优化五:添加注释

虽然注释并不参与编译,但是在开发中注释也具有十分重要的作用。

  1. 有助于理解
  2. 帮助修补程序或快速修复
  3. 有助于加快开发过程
  4. 有助于提高协作效率
//模拟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陷阱与缺陷》或许在这里面可以找到你想要的更多答案!


相关文章
|
7月前
|
设计模式 算法 程序员
这些Coding套路你不会还不知道吧?
这些Coding套路你不会还不知道吧?
60 0
|
2月前
|
搜索推荐 Python
Leecode 101刷题笔记之第五章:和你一起你轻松刷题(Python)
这篇文章是关于LeetCode第101章的刷题笔记,涵盖了多种排序算法的Python实现和两个中等难度的编程练习题的解法。
23 3
|
2月前
|
算法 C++ Python
Leecode 101刷题笔记之第四章:和你一起你轻松刷题(Python)
这篇博客是关于LeetCode上使用Python语言解决二分查找问题的刷题笔记,涵盖了从基础到进阶难度的多个题目及其解法。
20 0
|
6月前
|
C语言
|
7月前
|
存储 开发工具 文件存储
Python的核心知识点整理大全66(已完结撒花)
Python的核心知识点整理大全66(已完结撒花)
120 4
|
7月前
|
存储 Java C++
【python基础题】——知识点选择、填空、简答
【python基础题】——知识点选择、填空、简答
|
存储 算法 C语言
20230806算法题(C语言)(适合专升本的同学和入门的小白)
20230806算法题(C语言)(适合专升本的同学和入门的小白)
|
编译器 程序员 C语言
程序的编译与链接(预处理详解)+百度面试笔试题+《高质量C/C++编程指南》笔试题
如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。
114 0
|
C++
AcWing语法基础课笔记 第六章 C++中的函数
函数让代码变得更加简洁。 ——闫学灿
113 0
|
存储 算法 Python
Python蓝桥杯易错点整理和心得总结【一】
Python蓝桥杯易错点整理和心得总结【一】
317 0
Python蓝桥杯易错点整理和心得总结【一】