编程终极技能-调试(下)

简介: 编程终极技能-调试

5. 如何写出好的(易于调试的代码)


常见技巧:


  • 尽量使用assert
  • 尽量使用 const
  • 养成良好的编码习惯
  • 添加必要的注释


实例二


【strcpy库函数的实现】


/***
*char *strcpy(dst, src) - copy one string over another
*
*Purpose:
*       Copies the string src into the spot specified by
*       dest; assumes enough room.
*
*Entry:
*       char * dst - string over which "src" is to be copied
*       const char * src - string to be copied over "dst"
*
*Exit:
*       The address of "dst"
*
*Exceptions:
*******************************************************************************/
char * strcpy(char * dst, const char * src)
{
        char * cp = dst;
 assert(dst && src);
        while( *cp++ = *src++ )
               ;     /* Copy src over dst */
        return( dst );
}

仔细观察,这里库函数的第二个参数是被const修饰的。那么这里的const有什么作用呢?


const 的作用


#include <stdio.h>
//代码1
void test1()
{
    int n = 10;
    int m = 20;
    int *p = &n;
    *p = 20;//编译通过
    p = &m; //编译通过
}
void test2()
{
     //代码2
    int n = 10;
    int m = 20;
    const int* p = &n;
    *p = 20;//编译失败
    p = &m; //编译通过
}
void test3()
{
    int n = 10;
    int m = 20;
    int *const p = &n;
    *p = 20; //编译通过
    p = &m;  //编译失败
}
int main()
{
    //测试无cosnt的
   test1();
    //测试const放在*的左边
    test2();
    //测试const放在*的右边
    test3();
    return 0;
}


const修饰指针时:


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


assert 的作用


assert的作用是:当程序运行时,若assert的括号中的条件不满足时,程序会强制提醒程序员。例如:


但是assert需要包含头文件:#include<assert.h>。


#include<stdio.h>
#include<assert.h>
int div1(int a, int b)
{
  assert(0);
  int ret = a / b;
  return ret;
}
int main()
{
  int a = 4;
  int b = 1;
  //scanf("%d %d", &a, &b);
  int ret = div1(a, b);
  printf("%d", ret);
  return 0;
}

23c65a1e406b2ae3ee92594f6d368922_5756db0538684b4fbc2ee1d89019ffb5.png


只要程序不满足assert括号中的语句,程序就会强制提醒用户出错的地方。


小练习:模拟实现strlen函数


#include<stdio.h>
#include<assert.h>
//模拟实现strlen函数
int MyStrlen(const char* arr)
{
  assert(arr != NULL);
  int count = 0;
  while (*arr != '\0')
  {
  count++;
  arr++;
  }
  return count;
}
int main()
{
  char arr[1000];
  gets(arr);//读取字符串
  int len = MyStrlen(arr);
  printf("%d \n", len);
  return 0;
}


这里要注意assert的使用和 const的使用。


6. 编程常见错误


编译型错误:


直接看错误提示信息(双击),解决问题。或者凭借经验就可以搞定。相对来说简单.


链接型错误:


看错误提示信息,主要在代码中找到错误信息中的标识符,然后定位问题所在。一般是标识符名不存在或者拼写错误。


运行时错误:


借助调试,逐步定位问题。最难搞。


所以,还是要靠我们做一个有心人,积累排错经验。


7.完结


本章的内容就到这里啦,若有不足,欢迎评论区指正,最后,希望大佬们多多三连吧,下期见!


相关文章
|
8月前
|
自然语言处理 安全 数据管理
二维码一个个生成太麻烦?试试批量生码功能
如果你正在处理成百上千条数据,又正好有生成二维码的需求,不妨试试这个工具。几分钟的学习,可能就能为你节省几天的工作时间
二维码一个个生成太麻烦?试试批量生码功能
|
6月前
|
UED 开发者 容器
36.[HarmonyOS NEXT Row案例四] 打造精美图标按钮:垂直对齐与视觉平衡的艺术
在移动应用界面设计中,带图标的操作按钮是一种常见且实用的UI元素,它结合了图标的直观性和文本的描述性,能够有效提升用户体验。本教程将详细讲解如何使用HarmonyOS NEXT的Row组件创建一个带图标的操作按钮,重点介绍垂直对齐与视觉平衡的实现技巧,帮助开发者打造出专业、美观的交互界面。
137 4
编译QCefView+VS2019+QT5.15.2
本文介绍了如何编译QCefView项目,并在VS2019和Qt 5.15.2环境下集成,包括编译结果、要点、cmake部署Qt的方法和相关参考链接。
967 2
编译QCefView+VS2019+QT5.15.2
|
存储 安全 网络安全
网络安全法律框架:全球视角下的合规性分析
网络安全法律框架:全球视角下的合规性分析
357 1
|
负载均衡 Java Linux
管道,信号量,共享内存,socket的实际使用场景和NSPipe管道的使用
管道,信号量,共享内存,socket的实际使用场景和NSPipe管道的使用
265 0
|
搜索推荐 关系型数据库 MySQL
分享102个PHP源码,总有一款适合您
分享102个PHP源码,总有一款适合您
264 1
|
缓存 前端开发 安全
Angular 与 GraphQL 强势联合超厉害!现代前端数据获取新范式,开启高效开发新旅程!
【8月更文挑战第31天】在前端开发领域,Angular 与 GraphQL 的结合为数据获取带来了革命性的变化。Angular 凭借其强大的组件化开发模式和依赖注入特性,成为构建大型应用的理想选择。然而,在数据获取上,传统 RESTful API 显得力不从心。这时,GraphQL 出现了,它允许前端精确获取所需数据,避免了数据过度获取或不足的问题。通过一个简单的查询语句,即可一次性获取所需数据,极大地提升了效率。虽然在实际应用中仍需解决缓存和错误处理等问题,但这种结合无疑为现代前端数据获取开辟了新道路,推动技术不断进步。
146 0
|
算法 C++
黑马c++ STL常用算法 笔记(2) 查找算法
黑马c++ STL常用算法 笔记(2) 查找算法
|
关系型数据库 Unix 数据库
PostgreSQL语句大全
PostgreSQL是一个免费的对象-关系数据库服务器(ORDBMS),在灵活的BSD许可证下发行。PostgreSQL开发者把它念作post-gress-Q-L。PostgreSQL的Slogan是"世界上最先进的开源关系型数据库"。基本语法CREATEFUNCTION//声明创建函数ADD(INTEGER,INTEGER)//定义函数名称RETURNSINTEGER//定义函数返回值'//定义函数体'--使用函数。......
371 1
|
存储
数据结构之二叉树的实现(一)
之前给大家介绍了有关堆的实现,那么这里小编就给大家带来今天的重头戏——二叉树的实现,以及介绍。
176 0