【C语言初阶(19)】实用的 VS 调试技巧
文章目录
- Ⅰ 调试的介绍
- Ⅱ 常用调试快捷键
- Ⅲ 调试的时候查看程序当前信息
- ⒈查看临时变量的值
- ⒉查看内存信息
- ⒊查看调用堆栈
- ⒋查看汇编信息
- ⒌查看寄存器信息
- Ⅳ 观察形参指针指向的数组
- Ⅴ 易于调试的代码该如何编写
- ⒈const 修饰指针变量
- ⒉良好代码示范
- Ⅵ 编程中常见的错误
Ⅰ 调试的介绍
1. 什么是调试
- 调试(Debug),又称为除错,是发现和减少计算机程序或电子仪器设备中程序的错误的一个过程。
2. 调试的基本步骤
- 发现程序的错误的存在(开发 → 测试 → 用户)。
- 以隔离、消除等方式对错误进行定位。
- 确定错误产生的原因。
- 提出纠正错误的解决办法。
- 对程序错误允以改正,重新测试。
3. Debug 和 Release 的介绍
- Debug 称为调试版本,它包含有各种调试信息,且不作任何优化,所占空间更大。
- Release 称为发布版本,此版本进行了优化,不包含调试信息,用户使用的以及测试人员检测的都是这个版本。
4. 调试环境的准备
- 在环境中选择 Debug 选项,只有在这里才可以进行调试。
Ⅱ 常用调试快捷键
- 注意:以下所有快捷键如果不起作用的话,请搭配 FN 键使用。
F5
- 启动调试:用于直接跳到下一个断点处,经常和 F9 成对使用。
F9
- 创建断点和取消断点:断点的重要作用,可以在程序的任意位置设置断点。
- 这样就可以使得程序在想要的位置随意停止执行,从而一步步执行下去。
F10
- 逐过程调试:通常用于处理一个过程,一个过程可以是一次函数调用,或是一条语句。
- 当碰到函数调用时,不会进到函数内部,无法观测到函数体内部的细节。
F11
- 逐语句调试:每次都执行一条语句,可以进入函数体观察函数内部的细节。
CTRL + F5
- 开始执行不调试:用于让程序直接运行起来而不进行调试,学习编程初期使用的最多的就是这个。
Ⅲ 调试的时候查看程序当前信息
- 进入调试之后,在调试窗口中才能看到下面的信息。
⒈查看临时变量的值
- 在调试开始之后,用于观察变量内存放的值的变化。
- 自动窗口与监视窗口都能够观察到局部变量的信息。
自动窗口与监视窗口的区别
- 自动窗口会自动显示所有局部变量的信息(不管你是否需要),随着调试的进程,自动窗口内所观察的变量有时会自动出现,有时又会自动消失。
- 监视需要程序员手动输入(想观察谁就输入谁),观察的变量不会随着调试的进程而消失,强雷建议使用监视窗口来观察局部变量的值。
⒉查看内存信息
⒊查看调用堆栈
调用堆栈
- 调用堆栈,反应的是函数的调用关系。
- 后期当遇到很复杂的函数关系的时候,就可以使用调用堆栈来理清函数之间的调用关系。
举个栗子
- 现有以下代码:
- main 函数调用了 test1,test1调用了 test2,test2 → test3。
- 而 main 函数又是被其他函数所调用的。
- 函数调用采用的是数据结构中 栈 的先进后出的特性,先调用的函数后结束。
⒋查看汇编信息
- 查看 C 语言代码所翻译出来的汇编代码。
⒌查看寄存器信息
- 用于查看当前运行环境的寄存器的使用信息。
Ⅳ 观察形参指针指向的数组
- 众所周知,在给函数传数组名的时候,传递的是数组首元素的地址;
- 这样一来的话,在函数内部调试的时候,只是输入个数组名就不能很好的观察到数组内部的值的变化。
- 但是,只要在我们想要观察的数组指针变量名后面加上 " 逗号 " 和 " 想要观察的元素个数 " 就可以很好观察到数组内部元素的值了。
二维数组同理
- 如果将二维数组名作为参数传给函数的话,观察函数形参的二维数组指针也就只能观察到原数组第一行的内容。
- 因为二维数组的数组名为第一行的地址。
Ⅴ 易于调试的代码该如何编写
1. 什么是高质量的代码
- 代码能够正常运行。
- 尽可能少的 BUG(不可能没有BUG)。
- 可执行效率够高。
- 可读性要强。
- 可维护性高。
- 注释要清晰,能让人看得懂。
- 相应文档齐全。
2. 常用编程技巧
- 使用 assert 断言。
- assert 的表达式如果为假则直接结束程序并报错,使用 assert 来判断指针是否指向 NULL。
- 尽量使用 const 修饰变量(包括变量和指针变量)。
- 养成良好的编码风格。
- 添加必要的注释。
- 避免编码的陷阱。
⒈const 修饰指针变量
- const 可以修饰普通的变量,让变量的值无法被修改,从而变成常变量(本质任然是个变量)。
-
同样的,const 也可以用来修饰指针变量。const 修饰指针有两种形式。
-
对于指针变量来说,应该关注的有两点:
- 指针变量本身能不能改;
- 指针变量指向的那个变量能不能改。
-
const 放置的位置就决定了能不能修改这两种值。
1. const 放在 * 的左边
const int* p = &n; //只要 const 放在 * 的左边,这两中写法就都一样。
int const* p = &n;
- 限制的是指针指向的内容,也就是限制了 *p,让指针指向的那个变量的值无法被修改。
- 但是指针变量是可以修改的,指针可以指向其他变量。
2. const 放在 * 的右边
int* const p = &n;
- 限制的是指针变量本身,在 p 已经指向了 n 之后,p 就不能再被修改为指向其他变量了。
- 但是可以通过指针变量修改指向的内容。
- 当在 * 的两边都加上 const 之后,p 就只能指向 n,并且*p 也不能改变 n 的值了。
⒉良好代码示范
模式实现 strcpy
#include <stdio.h>
#include <assert.h>//我只想改变 str1,不想改变 str2 ,const 保证 src 指针指向的 str2 数组内的值不会一不小心被修改
char* my_strcpy(char* dest, const char* src)
{assert(dest && src); //当传过来的两个指针为 NULL 时,直接结束程序并报错char* ret = dest; //保存目的地首元素的地址,一会还要传回去while (*dest++ = *src++) //直到 *src = \0,然后由于是后置++,再将 \0 也赋值给 dest 为止{;}return ret; //返回 dest 的起始地址
} int main()
{char str1[20] = "***************";char str2[] = "hello word!";printf("%s\n", my_strcpy(str1, str2));return 0;
}
模拟实现 strlen
#include <stdio.h>
#include <assert.h>size_t my_strlen(const char* str) //防止原数组中得内容不小心被修改
{assert(str); //判断传过来的指针的有效性 (!= NULL)const char* end = str; //标识字符串末尾while (*end++); //当 end 指向 \0 时退出循环return (end - str - 1); //指针 - 指针得到同一块空间的两个地址之间的元素个数//-1 是因为后置 ++ 的副作用,要把 \0 的那一个元素去掉
}int main()
{char str[] = "hello word!";printf("%zd\n", my_strlen(str));return 0;
}
Ⅵ 编程中常见的错误
1. 编译型错误
- 一般为语法错误。
- 这类错误直接查看错误提示信息(双击),解决问题,或者凭借经验就可以搞定。
2. 链接型错误
- 一般为未包含头文件、符号名(函数名、变量名)不存在或者拼写错误。
- 看错误提示信息,主要在代码中找到错误信息中的标识符,然后定位问题所在。
3. 运行时错误
- 一般为程序运行起来时发现的错误。
- 只能借助调试定位到问题所在,这种问题最难解决。
相关文章:

【C语言初阶(19)】实用的 VS 调试技巧
文章目录 Ⅰ 调试的介绍Ⅱ 常用调试快捷键Ⅲ 调试的时候查看程序当前信息⒈查看临时变量的值⒉查看内存信息⒊查看调用堆栈⒋查看汇编信息⒌查看寄存器信息 Ⅳ 观察形参指针指向的数组Ⅴ 易于调试的代码该如何编写⒈const 修饰指针变量⒉良好代码示范 Ⅵ 编程中常见的错误 Ⅰ 调…...

虚拟机之间配置免密登录
目录 一、配置主机名映射 二、虚拟机配置SSH免密登录 三、验证 一、配置主机名映射 即修改/etc/hosts文件,将几台服务器和主机名进行映射。 注意每台服务器都要进行同样的配置。这样在各自服务器下,我们就可以通过主机名访问对应的ip地址了。 当然&…...

【contenteditable属性将元素改为可编辑状态】
元素添加contenteditable属性之后点击即可进入编辑状态 像这种只修改一条属性不必再打开弹框进行编辑,使用contenteditable会很方便 添加失焦、回车、获焦事件 如 <p :contenteditable"item.contenteditable || false"keydown.enter"key($event…...

Android 第三方库CalendarView
Android 第三方库CalendarView 根据需求和库的使用方式,自己弄了一个合适自己的日历,仅记录下,方便下次弄其他样式的日历。地址 需求: 只显示当月的数据 默认的月视图有矩形的线 选中的天数也要有选中的矩形框 今天的item需要…...

钉钉群消息推送
1. 添加钉钉群机器人 PC端登录(当前版本手机端无法进行推送关键词设置),群设置--> 机器人 --> webhook进行安全设置复制webhook对应的url 2. 群消息推送 钉钉群消息支持纯文本和markdown类型 2.1 调用示例源码 import com.alibaba.…...
css clip-path 属性介绍
circle() – 圆 语法:circle( [<shape-radius>]? [at <position>]? ) shape-radius 圆的半径 position 圆的中心点位置 使用方法: clip-path: circle(); // 以元素的中心点为圆的中心点,最小宽度一半为圆的半径。clip-path: c…...

Python之pyinstaller打包exe填坑总结
一、起因 编写了一个提取图片中文字的python脚本,想传给同事使用,但是同事电脑上没有任何python环境,更没有安装python库,因此想到通过pyinstaller打包成exe程序传给同事使用,于是开始了不断地挖坑填坑之旅 import p…...
Form Generator 表单JSON数据储存以及JSON回显表单
一、form-generator是什么?✨ ⭐️ 🌟 form-generator的作者是这样介绍的:Element UI表单设计及代码生成器,可将生成的代码直接运行在基于Element的vue项目中;也可导出JSON表单,使用配套的解析器将JSON解析成真实的表单。 但目前它提供的组件并不能满足我们在项目中的…...

Python - OpenCV识别条形码、二维码(已封装,拿来即用)
此代码可识别条形码和二维码,已封装好,拿来即用: import cv2 import pyzbar.pyzbar as pyzbar import numpy from PIL import Image, ImageDraw, ImageFontclass CodeScan():def __init__(self):super(CodeScan, self).__init__()def decode…...
Python如何快速实现爬取网页?
首先我们对要编写的爬虫程序进行简单地分析,该程序可分为以下三个部分: 拼接 url 地址发送请求将照片保存至本地 明确逻辑后,我们就可以正式编写爬虫程序了。 导入所需模块 本节内容使用 urllib 库来编写爬虫,下面导入程序所用…...

怎么才能远程控制笔记本电脑?
为什么选择AnyViewer远程控制软件? 为什么AnyViewer是远程控制笔记本电脑软件的首选?以下是选择AnyViewer成为笔记本电脑远程控制软件的主要因素。 跨平台能力 AnyViewer作为一款跨平台远程控制软件,不仅可以用于从一台Windows电…...
【3】C++实现多进程、多线程
系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言一、同步与互斥1、【thread】同步并发的方法(1)创建、终止、等待、分离线程的方法1.创建线程形式1:使用一个循环执行的函数创建一个线程形式2:…...
Linux用户权限信息、chmod以及chown命令
权限修改 权限信息chmod命令chown命令 权限信息 在Linux系统中,每个文件和目录都包含了权限信息,用于控制对其的访问权限。 文件权限:Linux系统中的文件权限由三组权限表示,分别是所有者权限、组权限和其他用户权限。 所有者权…...

利用vscode--sftp,将本地项目/文件上传到远程服务器中详细教程
1、首先在 vscode 中下载 sftp: 2、然后在 vscode 中打开本地将要上传的项目或文件: 3、安装完后,使用快捷键 ctrlshiftP 打开指令窗口,输入 sftp:config ,回车,在当前目录中会自动生成 .vscode 文件夹及 s…...
java List和数组相互转换的方法总结
Java中,可以通过以下方法将List转换为数组: List<String> list new ArrayList<>(); String[] array list.toArray(new String[0]);在这个例子中,我们将一个String类型的List转换为String类型的数组。需要注意的是,…...

【音频分离】demucs V3的环境搭建及训练(window)
文章目录 一、环境搭建(1)新建虚拟环境,并进入(2)安装pyTorch(3)进入代码文件夹,批量安装包(4)安装其他需要的包 二、数据集准备(1)下…...
JAVA环境变量配置(windows)
windows配置环境变量(大小写不区分): 新建JAVA_HOME:jdk的根目录 D:\Java\jdk1.8.0_71Path(必须)%JAVA_HOME%\bin新建(类路径)CLASSPATH: .;D:\Java\jdk1.8.0_71\lib(或者.;%JAVA_HO…...

爬虫教程1_Xpath 入门教程
Xpath 入门教程 在编写爬虫程序的过程中提取信息是非常重要的环节,但是有时使用正则表达式无法匹配到想要的信息,或者书写起来非常麻烦,此时就需要用另外一种数据解析方法,也就是本节要介绍的 Xpath 表达式。 Xpath表达式 XPath…...

Python爬虫教程篇+图形化整理数据(数学建模可用)
一、首先我们先看要求 1.写一个爬虫程序 2、爬取目标网站数据,关键项不能少于5项。 3、存储数据到数据库,可以进行增删改查操作。 4、扩展:将库中数据进行可视化展示。 二、操作步骤: 首先我们根据要求找到一个适合自己的网…...
数字安全观察·数据安全分析方向
政策形势方面,全球均在加快制定并完善数字经济与数据安全相关政策法规。国际方面,欧盟、美国、英国、印度、俄罗斯等国家持续完善数据安全方面的法律政策,并且尤其关注数据跨境传输方面的问题。同时世界各国都着力关注人工智能数据安全风险&a…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...

Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...