当前位置: 首页 > news >正文

实用调试技巧(2)

文章目录

    • 6. 如何写出好(易于调试)的代码
      • 6.1 优秀的代码:
      • 6.2 示范:
      • 6.3 const的作用
    • 7. 编程常见的错误
      • 7.1 编译型错误
      • 7.2 链接型错误
      • 7.3 运行时错误
  • 附:

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

6.1 优秀的代码:

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

常见的coding技巧:

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

6.2 示范:

模拟实现库函数:strcpy

我们先来看一下strcpy是如何使用的:

#include <stdio.h>
#include <string.h>int main()
{char arr1[] = "hello bit";char arr2[20] = "xxxxxxxxxxxxx";//strcpy(arr2, arr1);//printf("%s\n", arr2);printf("%s\n", strcpy(arr2, arr1));return 0;
}

接下来我们来实现它:

#include <stdio.h>void my_strcpy(char* dest, char* src)
{while (*src != '\0'){*dest = *src;dest++;src++;}*dest = *src;// \0 的拷贝
}int main()
{char arr1[] = "hello bit";char arr2[20] = "xxxxxxxxxxxxx";my_strcpy(arr2, arr1);printf("%s\n", arr2);return 0;
}

我们还可以使用assert对它进行优化:

#include <stdio.h>
#include <assert.h>void my_strcpy(char* dest, char* src)
{//断言assert(dest != NULL);assert(src != NULL);while (*src != '\0'){*dest = *src;dest++;src++;}*dest = *src;// \0 的拷贝
}int main()
{char arr1[] = "hello bit";char arr2[20] = "xxxxxxxxxxxxx";char* p = NULL;//my_strcpy(p, arr1);my_strcpy(arr2, arr1);printf("%s\n", arr2);return 0;
}

通过assert,我们可以确保某些事情不会发生,一旦发生,它就会报错,这样就能方便我们快速找到错误。

我们还可以将字符和\0的拷贝放到一起:

#include <stdio.h>
#include <assert.h>void my_strcpy(char* dest, char* src)
{//断言assert(dest != NULL);assert(src != NULL);while (*dest = *src)//赋值表达式,比如把h赋给*dest,表达式的结果就是h的ASCII码值{dest++;src++;}}int main()
{char arr1[] = "hello bit";char arr2[20] = "xxxxxxxxxxxxx";char* p = NULL;//my_strcpy(p, arr1);my_strcpy(arr2, arr1);printf("%s\n", arr2);return 0;
}

还可以这样写:

#include <stdio.h>
#include <assert.h>void my_strcpy(char* dest, char* src)
{//断言assert(dest != NULL);assert(src != NULL);while (*dest++ = *src++)//赋值表达式,比如把h赋给*dest,表达式的结果就是h的ASCII码值{;//空语句}}int main()
{char arr1[] = "hello bit";char arr2[20] = "xxxxxxxxxxxxx";char* p = NULL;//my_strcpy(p, arr1);my_strcpy(arr2, arr1);printf("%s\n", arr2);return 0;
}

此外,我们还可以对返回类型进行优化:

#include <stdio.h>
#include <assert.h>//函数返回的是目标空间的起始地址
char* my_strcpy(char* dest, char* src)
{char* ret = dest;//断言assert(dest != NULL);assert(src != NULL);while (*dest++ = *src++)// 赋值表达式,比如把h赋给*dest,表达式的结果就是h的ASCII码值{;//空语句}return ret;
}int main()
{char arr1[] = "hello bit";char arr2[20] = "xxxxxxxxxxxxx";char* p = NULL;//my_strcpy(p, arr1);//my_strcpy(arr2, arr1);//printf("%s\n", arr2);printf("%s\n", my_strcpy(arr2, arr1));return 0;
}

另外,为了保证传进去的arr1不被修改,我们还可以加上const进行修饰:

#include <stdio.h>
#include <assert.h>//函数返回的是目标空间的起始地址
char* my_strcpy(char* dest, const char* src)
{char* ret = dest;//断言assert(dest != NULL);assert(src != NULL);while (*dest++ = *src++)// 赋值表达式,比如把h赋给*dest,表达式的结果就是h的ASCII码值{;//空语句}return ret;
}int main()
{char arr1[] = "hello bit";char arr2[20] = "xxxxxxxxxxxxx";char* p = NULL;//my_strcpy(p, arr1);//my_strcpy(arr2, arr1);//printf("%s\n", arr2);printf("%s\n", my_strcpy(arr2, arr1));return 0;
}

6.3 const的作用

有以下两种方式可以修改num的值:

int main()
{int num = 10;num = 20;int* p = &num;*p = 200;return 0;
}

现在我们加上const:

#include <stdio.h>int main()
{const int n = 100;//n = 200;//errint* p = &n;*p = 20;printf("%d\n", n);return 0;
}

加上const是为了不让n的值发生变化,但是现在我们却可以通过地址的方式来改变它,于是我们可以进行以下操作:

int main()
{const int n = 100;//n = 200;//err//int* p = &n;//*p = 20;//printf("%d\n", n);const int* p = &n;//*p = 20;//errreturn 0;
}

通过以上代码我们可以发现const是可以修饰指针的:

//const 修饰指针的时候
//当const 放在*的左边的时候,限制的是指针指向的内容,不能通过指针变量改变指针指向的内容,但是指针变量本身是可以改变的
//当const 放在*的右边的时候,限制的是指针变量本身,指针变量本身是不能改变的,但是指针指向的内容是可以通过指针来改变的#include <stdio.h>int main()
{int m = 10;int n = 100;//const可以修饰指针const int* p = &m;//*p = 0;//errp = &n;//okprintf("%d\n", m);return 0;
}
#include <stdio.h>int main()
{int m = 10;int n = 100;//const可以修饰指针int* const p = &m;*p = 0;//ok//p = &n;//errprintf("%d\n", m);return 0;
}
#include <stdio.h>int main()
{int m = 10;int n = 100;//const可以修饰指针const int* const p = &m;//*p = 0;//err//p = &n;//errprintf("%d\n", m);return 0;
}

练习:

模拟实现一个strlen函数

//模拟实现一个strlen函数
//assert
//const//size_t 是专门为sizeof设计的一个类型
//size_t --> unsigned int / unsigned long
//>=0#include <stdio.h>
#include <assert.h>size_t my_strlen(const char* str)
{assert(str != NULL);size_t count = 0;while (*str != '\0'){count++;str++;}return count;
}int main()
{char arr[] = "abc";size_t len = my_strlen(arr);printf("%zd\n", len);//zd是专门用来打印size_t类型的值的return 0;
}//%u 无符号整数的

7. 编程常见的错误

7.1 编译型错误

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

int main()
{int a = 10//编译期间找到的一般都是语法问题return 0;
}

7.2 链接型错误

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

//链接型错误是在链接期间发现的错误int Add(int x, int y)
{return x + y;
}int main()
{int ret = add(2, 3);return 0;
}

7.3 运行时错误

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

#include <stdio.h>int Add(int x, int y)
{return x - y;
}int main()
{int ret = Add(2, 3);printf("%d\n", ret);return 0;
}

附:

实用调试技巧(1)

相关文章:

实用调试技巧(2)

文章目录 6. 如何写出好&#xff08;易于调试&#xff09;的代码6.1 优秀的代码&#xff1a;6.2 示范&#xff1a;6.3 const的作用 7. 编程常见的错误7.1 编译型错误7.2 链接型错误7.3 运行时错误 附&#xff1a; 6. 如何写出好&#xff08;易于调试&#xff09;的代码 6.1 优…...

海外ASO优化之如何优化游戏应用

如果我们发布了一款手机游戏或者管理了一款手机游戏&#xff0c;那么需要确保我们的手机游戏对合适的人可见&#xff0c;目的是增加应用的下载量。 1、优化游戏元数据的关键词。 Apple和Google在应用商店中为我们提供有限的空间&#xff0c;来描述手机游戏及其优势。我们需要使…...

SpringMVC: Java Web应用开发的框架之选

引言 在当今的软件开发领域中&#xff0c;Web应用的需求不断增长。为了满足这种需求&#xff0c;各种Web框架应运而生。其中&#xff0c;SpringMVC作为一种优秀的Java Web框架&#xff0c;受到广泛关注和使用。本文将以文章的形式给您讲解SpringMVC的重要概念、工作原理和核心…...

【华为设备升级】AR路由器升级设备软件示例

升级设备软件示例 通过介绍设备升级的具体步骤&#xff0c;帮助用户顺利完成系统设备升级。 组网需求 设备当前系统软件版本已经不能满足用户需要&#xff0c;用户需要更大的规格和部署更多的特性&#xff0c;此时用户需要对系统软件进行升级。 如图1所示&#xff0c;网络中的某…...

Dataset 的一些 Java api 操作

文章目录 一、使用 Java API 和 JavaRDD<Row> 在 Spark SQL 中向数据帧添加新列二、foreachPartition 遍历 Dataset三、Dataset 自定义 Partitioner四、Dataset 重分区并且获取分区数 一、使用 Java API 和 JavaRDD 在 Spark SQL 中向数据帧添加新列 在应用 mapPartition…...

Vue + Element UI 前端篇(十一):第三方图标库

Vue Element UI 实现权限管理系统 前端篇&#xff08;十一&#xff09;&#xff1a;第三方图标库 使用第三方图标库 用过Elment的同鞋都知道&#xff0c;Element UI提供的字体图符少之又少&#xff0c;实在是不够用啊&#xff0c;幸好现在有不少丰富的第三方图标库可用&…...

HDFS:Hadoop文件系统(HDFS)

Hadoop文件系统&#xff08;HDFS&#xff09;是一个分布式文件系统&#xff0c;主要用于存储和处理大规模的数据集。HDFS是Apache Hadoop的核心组件之一&#xff0c;能够支持上千个节点的集群&#xff0c;并能够处理PB级别的数据。 HDFS将大文件切割成小的数据块&#xff08;默…...

SpringMvc--综合案例

目录 1.SpringMvc的常用注解 2.参数传递 基础类型&#xff08;String&#xff09; 创建一个paramController类&#xff1a; 创建一个index.jsp 测试结果 复杂方式 ​编辑 测试结果 RequestParam 测试结果 PathVariable 测试结果 RequestBody pom.xml依赖导入 输…...

工业4.0时代生产系统对接集成优势,MES和ERP专业一体化管理-亿发

在现代制造业中&#xff0c;市场变化都在不断加速。企业面临着不断加强生产效率、生产质量和快速适应市场需求的挑战。在制造行业&#xff0c;日常管理中的ERP系统、MES系统就显得尤为重要。越来越多的企业正在采用MES系统和ERP管理系统的融合&#xff0c;以实现智能化生产管理…...

IT运维监控系统和网络运维一样吗

IT运维监控系统和网络运维不是一样的。IT运维监控系统是一系列IT管理产品的统称&#xff0c;它所包含的产品功能强大、易于使用、解决方案齐全&#xff0c;可一站式满足用户的各种IT管理需求。而网络运维是指对网络设备进行监控、维护和管理&#xff0c;包括硬件故障的排除、软…...

c语言flag的使用

flag在c语言中标识某种状态或记录某种信息&#xff0c;可以通过修改flag中来控制程序流程,判断某种状态是否存在或记录某种信息 操作:(1)初始化 (2)赋值 (3)判断 (4)修改 (5)去初始化 #include <stdlib.h>int power_state_check;int main() {int i 0;power_state_check…...

docker push image harbor http 镜像

前言 搭建的 harbor 仓库为 http 协议&#xff0c;在本地登录后&#xff0c;推送镜像发生如下报错&#xff1a; docker push 192.168.xx.xx/test/grafana:v10.1.1 The push refers to repository [192.168.xx.xx/test/grafana] Get "https://192.168.xx.xx/v2/": dia…...

羊城杯2023 部分wp

目录 D0nt pl4y g4m3!!!(php7.4.21源码泄露&pop链构造) Serpent(pickle反序列化&python提权) ArkNights(环境变量泄露) Ez_misc(win10sinpping_tools恢复) D0nt pl4y g4m3!!!(php7.4.21源码泄露&pop链构造) 访问/p0p.php 跳转到了游戏界面 应该是存在302跳转…...

解读Java对Execl读取数据

1.读取execl文件路径,或者打开execl // 初始化文件流FileInputStream in = null;in = new FileInputStream(new File(path));workbook = new XSSFWorkbook(in);sheet = workbook.getSheetAt(0);rows = sheet.getPhysicalNumberOfRows(); 2.读取execl中sheet页数,即获取当前E…...

RHCE——十七、文本搜索工具-grep、正则表达式

RHCE 一、文本搜索工具--grep1、作用2、格式3、参数4、注意5、示例5.1 操作对象文件&#xff1a;/etc/passwd5.2 grep过滤命令示例 二、正则表达式1、概念2、基本正则表达式2.1 常见元字符2.2 POSIX字符类2.3 示例 3、扩展正则表达式3.1 概念3.2 示例 三、作业1、作业一2、作业…...

小程序实现摄像头拍照 + 水印绘制

文章标题 01 功能说明02 使用方式 & 效果图2.1 基础用法2.2 拍照 底部定点水印 预览2.3 拍照 整体背景水印 预览 03 全部代码3.1 页面布局 html3.2 业务核心 js3.3 基础样式 css 01 功能说明 需求&#xff1a;小程序端需要调用前置摄像头进行拍照&#xff0c;并且将拍…...

SpringMVC:从入门到精通,7篇系列篇带你全面掌握--三.使用SpringMVC完成增删改查

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于SpringMVC的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 效果演示 一.导入项目的相关依赖 二.…...

ABAP GN_DELIVERY_CREATE 报错 VL 561

GN_DELIVERY_CREATE 去创建内向交货单的时候。 报错 VL 561 Essential transfer parameters are missing in record 表示一些必输字段没输入 诸如一些&#xff0c;物料号。单位。等一些字段 输入之后即可 DATA: ls_return TYPE bapireturn.DATA: lt_return TYPE STANDARD T…...

AWS-数据库迁移工具DMS-场景:单账号跨区域迁移RDS for Mysql

参考文档&#xff1a; 分为几个环节&#xff1a; 要使用 AWS DMS 迁移至 Amazon RDS 数据库实例&#xff1a; 1.创建复制实例 有坑内存必须8g或者以上&#xff0c;我测试空库 都提示内存不足 2.创建目标和源终端节点 目标空库也得自己创建哈 3.刷新源终端节点架构 4.创建迁…...

【漏洞复现】E-office文件包含漏洞

漏洞描述 Weaver E-Office是中国泛微科技(Weaver)公司的一个协同办公系统。泛微 E-Office 是一款标准化的协同 OA 办公软件,实行通用化产品设计,充分贴合企业管理需求,本着简洁易用、高效智能的原则,为企业快速打造移动化、无纸化、数字化的办公平台。 该漏洞是由于存在…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

JS设计模式(4):观察者模式

JS设计模式(4):观察者模式 一、引入 在开发中&#xff0c;我们经常会遇到这样的场景&#xff1a;一个对象的状态变化需要自动通知其他对象&#xff0c;比如&#xff1a; 电商平台中&#xff0c;商品库存变化时需要通知所有订阅该商品的用户&#xff1b;新闻网站中&#xff0…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...