const函数和assert函数:提高代码质量的利器

简介: const函数和assert函数:提高代码质量的利器

前言

在C++中,const函数和assert函数是非常重要的概念。它们可以帮助我们确保代码的正确性和可靠性。那么在本期,我们将深入探讨这两个概念的作用和用法

一、如何写出优秀的代码?

什么是优秀的代码?

优秀的代码要符合以下特点:

1. 代码运行正常

2. bug很少

3. 效率高

4. 可读性高

5. 可维护性高

6. 注释清晰

7. 文档齐全

较好的编码建议:

1. 使用assert

2. 尽量使用const

3. 养成良好的编码风格

4. 添加必要的注释

5. 避免编码的陷阱。

举个例子:

模拟实现库函数:strcpy

strcpy是一个C语言中的字符串复制函数,用于将一个字符串的内容复制到另一个字符串中。它的原型如下:char *strcpy(char *dest, const char *src);

dest是目标字符串的指针,src是源字符串的指针。strcpy会将源字符串的内容复制到目标字符串中,直到遇到\0为止。需要注意的是,如果目标字符串不够大,可能会导致缓冲区溢出的问题。因此,在使用strcpy时,需要保证目标字符串足够大。

char *my_strcpy(char* dest,  char* src)
{
  char* ret = dest;
  while (*dest++ = *src++)
  {
    ;
  }
  return ret;
}
int main()
{
  char arr1[] = "Hello world!";
  char arr2[20] = "xxxxxxxxxxxxxxxxxxx";
  printf("%s\n", arr2);
  printf("%s\n",my_strcpy(arr2, arr1));
  printf("%s\n", strcpy(arr2, arr1));
  printf("%s\n", arr2);
  return 0;
}

我们自主实现的strcpy函数是否有问题呢?又或者说是否完美呢?

我们仔细观察my_strcpy这个函数,形参是两个指针类型,并且根据strcpy函数的功能,我们就会发现这个函数的缺陷。

1.源字符串不能被修改。

2.函数my_strcpy函数形参为源字符串的指针,需要避免传进去的指针不是NULL。

这里就需要引进我们的const,和assert。

二、assert

以以下代码为例:

char *my_strcpy(char* dest,  char* src)
{
  char* ret = dest;
  while (*dest++ = *src++)
  {
    ;
  }
  return ret;
}
int main()
{
  char arr1[] = "Hello world!";
  char arr2[20] = "xxxxxxxxxxxxxxxxxxx";
    char *p=NULL;
  printf("%s\n",my_strcpy(p, arr1));
  printf("%s\n", strcpy(arr2, arr1));
  printf("%s\n", arr2);
  return 0;
}

我们创建一个指向为NULL的指针,把他传入到my_strcpy的函数中,运行我们会发现,程序崩了(没有输出结果),在其他复杂的程序中很可能会遇到这样的问题,一行一行的找错误又会很麻烦,那要怎么办呢?这时候就可以使用我们的assert来解决。

在函数执行前先进行断言:

char *my_strcpy(char* dest, char* src)
{
  assert(src != NULL);
  assert(dest != NULL);
  char* ret = dest;
  while (*dest++ = *src++)
  {
    ;
  }
  return ret;
}
int main()
{
  char arr1[] = "Hello world!";
  char arr2[20] = "xxxxxxxxxxxxxxxxxxx";
  char* p = NULL;
  printf("%s\n",my_strcpy(p, arr1));
  printf("%s\n", strcpy(arr2, arr1));
  printf("%s\n", arr2);
  return 0;
}

这时我们再次运行就会发现它会报错,并且把错误信息以及错误位置都显示了出来,这样会更便于我们排错。

三、const

前边我们了解到,const修饰后的变量不可以被修改,并没有进行详细介绍,接下来我将会给大家详细介绍以下const。

我们还是以代码为例:

int main()
{
  const int a = 10;
  int b = 100;
  const int* p = &a;
  //int const* p = &a;与const int* p效更一样。
  //*p = 20;//报错
  p = &b;//可行
  printf("%d", *p);
  return 0;
}

在VS上敲入以上代码,a在赋值为20时会发生报错,编译器不允许我们这样修改a的值,既然这样不允许那我们取地址使用指针修改,通过运行我们会发现真的把a的值改了。、

const相当于是将存放a房间的门锁上了,不可以直接对a进行修改,但是我们还可以用  “翻窗户”  这样的扫操作进行修改。

既然我们发现了这个漏洞,那我们将p也进行const修饰不就改不了了,我们可以发现,const不仅可以修饰变量还可以修饰指针。

那么接下来我们就针对const修饰指针进行详细介绍

情况一:

const左修饰:

当const在*左边时,限制的是*p,*p不允许被修改(不可以通过指针来修改其所指向的空间里的值,但是p可以改变(p可指向其他空间)。

int main()
{
  const int a = 10;
  int b = 100;
  const int* p = &a;
  //int const* p = &a;与const int* p效更一样。
  //*p = 20;//报错
  p = &b;//可行
  printf("%d", *p);
  return 0;
}

情况二:

const右修饰:

当const在*右边时,限制的是p,p不允许指向其他空间,但可以通过p修改其所指向空间里的值;

int main()
{
  int a = 10;
  int b = 100;
  int* const p = &a;
  *p = 20;//可行
  p = &b;//报错
  printf("%d", *p);
  return 0;
}

那我们都两边都加上const呢?

int main()
{
  int a = 10;
  int b = 100;
  const int* const p = &a;
  *p = 20;//报错
  p = &b;//报错
  printf("%d", *p);
  return 0;
}

这样就把p完全限制,无法进行修改。

我们了解完const和assert之后,再次对my_strcpy函数进行修改:

#include<stdio.h>
#include<string.h>
#include<assert.h>
char *my_strcpy(char* dest, const char* src)
{
  assert(src != NULL);
  assert(dest != NULL);//注意使用assert一定要包含头文件才可以使用
  char* ret = dest;
  while (*dest++ = *src++)
  {
    ;
  }
  return ret;
}
int main()
{
  char arr1[] = "Hello world!";
  char arr2[20] = "xxxxxxxxxxxxxxxxxxx";
  char* p = NULL;
  //printf("%s\n", arr2);
  printf("%s\n",my_strcpy(p, arr1));
  printf("%s\n", strcpy(arr2, arr1));
  printf("%s\n", arr2);
  return 0;
}

这样修改后代码才能更完美。


总结

通过本篇博客的学习,相信大家对于const函数和assert函数有了更深入的理解。这两个概念虽然看起来简单,但是却非常重要,它们可以帮助我们写出更加高效、可靠的代码。最后,需要强调的是,const函数和assert函数并不是万能的,它们只是我们编写高质量代码的一部分工具。在实际的开发过程中,我们还需要结合其他的编程技巧和工具来提高代码的质量和可靠性。

相关文章
|
缓存 运维 Shell
幻兽帕鲁爆内存优化方案
最近有很多小伙伴反馈说4C16G的服务器玩时间久了经常出现内存过满自动重启的情况,现在总结下linux和windows系统下怎么进行优化。
|
网络协议 网络性能优化 C++
C/C++工程师面试题(网络编程篇)
C/C++工程师面试题(网络编程篇)
219 0
|
存储 Apache
Apache Hudi Savepoint实现分析
Apache Hudi Savepoint实现分析
230 0
|
SQL 监控 搜索推荐
自动化测试平台V1.0版本正式上线啦!
自动化测试平台V1.0版本正式上线啦!
387 0
|
存储 前端开发 安全
webhook是什么 与API的区别在哪里
webhooks是一个api概念,是微服务api的使用范式之一,也被成为反向api,即:前端不主动发送请求,完全由后端推送。 举个常用例子,比如你的好友发了一条朋友圈,后端将这条消息推送给所有其他好友的客户端,就是 Webhooks 的典型场景。
webhook是什么 与API的区别在哪里
|
数据采集 存储 缓存
使用Scrapy进行网络爬取时的缓存策略与User-Agent管理
使用Scrapy进行网络爬取时的缓存策略与User-Agent管理
|
存储 分布式计算 搜索推荐
【大数据技术Hadoop+Spark】MapReduce之单词计数和倒排索引实战(附源码和数据集 超详细)
【大数据技术Hadoop+Spark】MapReduce之单词计数和倒排索引实战(附源码和数据集 超详细)
444 0
|
Android开发 iOS开发 开发者
uniapp开发ios应用证书获取方法和安装教程
ios应用无法像安卓应用那样直接从自己的服务器下载app安装而无需进行额外的设置,ios的安装要相对复杂一些。 ios的安装,是根据苹果开发者账号类型,根据证书和证书profile文件的不同,安装方法都有所不同的。主要是下面三种安装方法
660 0
|
机器学习/深度学习 缓存 并行计算
NVIDIA Tesla GPU系列P4、T4、P40以及V100参数性能对比
NVIDIA Tesla系列GPU适用于高性能计算(HPC)、深度学习等超大规模数据计算,Tesla系列GPU能够处理解析PB级的数据,速度比使用传统CPU快几个数量级,NVIDIA Tesla GPU系列P4、T4、P40以及V100是Tesla GPU系列的明星产品,云服务器吧分享NVIDIA Tesla GPU系列P4、T4、P40以及V100参数性能对比:
|
开发工具 git 开发者
【保姆级教程】白嫖老外的云服务器
【保姆级教程】白嫖老外的云服务器
【保姆级教程】白嫖老外的云服务器