C语言 vs. Visual Studio 中使用调试技巧

目录

1.什么是bug?

2.调试是什么?为什么调试很重要?

2.1 调试的基本步骤

 2.2 Debug和Release的介绍

 3.Windows环境调试介绍

3.1 调试环境的准备

3.2 学会快捷键

3.3编辑快捷键

3.4调试的时候查看程序当前信息

3.3.1 查看临时变量的值

此时我们就可以观察到每一步a和b的变化

3.3.2 查看内存信息​编辑

​编辑

4.多动手,常调试,才会有进步

4.1如何写出容易调试的代码

4.1.1 使用assert

4.1.2使用const

5. 编程常见的错误

5.1 编译型错误

5.2 链接型错误

5.3 运行时错误


C语言一直以来都是程序员们的首选,因为它是一种底层语言,可以直接访问计算机的内存和硬件资源。Visual Studio (VS)则是一款强大的集成开发环境(IDE),为开发者提供了丰富的工具和功能。在C语言开发中,调试是一个至关重要的环节。在本文中,我们将探讨C语言与Visual Studio结合使用的调试技巧,以便更轻松地诊断和解决问题。

1.什么是bug?

在C语言中,"bug" 是指程序中的错误、缺陷或不符合预期的行为。Bug可能导致程序运行不正确、崩溃或产生不期望的结果。Bugs可以包括各种类型的问题,如语法错误、逻辑错误、运行时错误、内存泄漏、性能问题等。通常,程序员的任务之一就是识别和修复这些bug,以确保软件的正确性和稳定性。

2.调试是什么?为什么调试很重要?

调试是在程序中识别和修复bug的过程。在软件开发过程中,几乎不可避免地会出现错误。这些错误可能是语法错误、逻辑错误、运行时错误或其他各种问题。调试是识别、定位和修复这些问题的关键步骤。没有合适的调试技巧,开发者将很难发现问题并进行修复,这可能导致软件的质量下降,甚至影响用户的体验。

2.1 调试的基本步骤

  (1)复现问题,确定程序中出现了问题

  (2)理解问题,确定问题的性质和位置

  (3)寻找问题,通过设置断点、单步执行、观察变量等方法找到具体问题位置

  (4)分析并解决问题,找到根本问题并解决

  (5)重新测试,在进行修复后,重新运行程序,确保问题已经解决

 2.2 Debug和Release的介绍

Debug 版本:

 (1)目的: Debug 版本主要用于开发和调试阶段,旨在帮助开发人员识别和修复代码中的问题。

 (2)特点: Debug 版本通常包括调试信息,使开发人员能够在调试器中跟踪程序的执行,查看变量的值,设置断点等。此外,通常不进行代码优化,以便更容易理解和调试代码。

 (3)性能: Debug 版本通常运行较慢,因为它包含了额外的调试信息和未经优化的代码。   

 (4)可维护性: 由于包含了详细的调试信息,Debug 版本的可维护性更高,但文件体积较大。 

Release 版本:

  (1)目的: Release 版本用于实际部署和生产环境中,它旨在提供最终用户的最佳性能和最小的资源占用。

  (2)特点: Release 版本通常进行了代码优化,以提高程序的执行效率。同时,它通常会去除调试信息,以减小可执行文件的大小,从而减少资源占用。

  (3)性能: Release 版本通常运行更快,因为它经过了编译器和链接器的优化处理,不包含调试信息。

  (4)可维护性: Release 版本的可维护性较低,因为它去除了调试信息,使得在生产环境中难以诊断和解决问题。

 3.Windows环境调试介绍

3.1 调试环境的准备

在环境中选择debug选项才能使得代码正常调试。

3.2 学会快捷键

最常使用的几个调试快捷键:

F5

启动调试,经常用来直接跳到下一个断点处。

注:如何设置断点

F9

创建断点和取消断点
断点的重要作用,可以在程序的任意位置设置断点。
这样就可以使得程序在想要的位置随意停止执行,继而一步步执行下去。

只需要点击需要断点行的任意位置摁F9即可。

除此之外也有一种更简便的方式

只需要鼠标左键点击需要断点行的最左侧位置即可。

F10

逐过程,通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句。

F11

逐语句,就是每次都执行一条语句,但是这个快捷键可以使我们的执行逻辑进入函数内部(这是最常用的)。

如下面这串代码(省略了头文件)

void Print(int n) {
	if (n > 9) {
		Print(n / 10);
		printf("%d ", n % 10);
	}
}
 
int main() {
	int n;
	scanf("%d", &n);
	Print(n);
	return 0;
}

这串代码是实现用递归方式实现打印一个整数的每一位。

当我们按下F10(或者F11)时开始单步执行代码

继续按下F10(或F11)时箭头往下走,到168行时我们输入任意一个整数,走到Print(n)函数时,如果继续按F10,我们得到的结果是

此时我们发现它直接完成了一整个函数调用过程

但是如果我们在走到Print(n)函数时,我们按下F11

此时我们发现箭头进入到Print函数去了,继续按下F11的话会一直在Print函数内部逐语句一步一步执行

CTRL+F5

开始执行不调试,如果你想让程序直接运行起来而不调试就可以直接使用。

3.3编辑快捷键

在写代码时,熟悉掌握一些编辑快捷键也能帮我们更好的完成代码。

Shift+Alt+Enter: 切换全屏编辑

Ctrl+U: 全部变为小写

Ctrl+Shift+U: 全部变为大写

Ctrl+Shift+V: 剪贴板循环 (可以直接看到最近复制的多次的结果)

Ctrl+Shift+L:删除当前行  (会连带删除行上所有的文字代码)

Ctrl+K+C:注释选定内容

Ctrl+K+U:取消注释选定内容

3.4调试的时候查看程序当前信息

3.3.1 查看临时变量的值

在调试的时候观察变量的值

在此代码中,如果我们需要观察在每一步执行后a和b的值,即可输入在监视里

    

  

此时我们就可以观察到每一步a和b的变化

3.3.2 查看内存信息

此时这里我们能看到a的地址以及a的值


4.多动手,常调试,才会有进步

一定要熟练掌握调试技巧。
初学者可能80%的时间在写代码,20%的时间在调试。但是一个程序员可能20%的时间在写
程序,但是80%的时间在调试。
以后可能会出现很复杂调试场景:多线程程序的调试等。
多多使用快捷键,提升效率。

4.1如何写出容易调试的代码

4.1.1 使用assert

#include <assert.h">
void assert( int expression );

assert 的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向 stderr 打印一条出错信息,然后通过调用 abort 来终止程序运行。

例如此代码中如果a和b的值相等,那么意味着不需要后续交换的步骤了,所以就会直接报错。 

如果频繁的调用assert会极大的影响程序的性能,增加额外的开销。

在调试结束后,可以通过在包含 #include 的语句之前插入 #define NDEBUG 来禁用 assert 调用

4.1.2使用const

const修饰指针变量的时候:

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

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

问:思考一下上述代码哪些地方会报错

5. 编程常见的错误

5.1 编译型错误

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

5.2 链接型错误

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

5.3 运行时错误

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

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值