系列文章目录

文章目录

系列文章目录前言一、解决方法二、详细步骤1.首先,打开microsoft visual studio 2017,选择【工具】2.在工具菜单中选择 【Visual Studio 命令提示】3.这时会弹出一个命令提示符窗口,在窗口中输入devenv /resetsettings,回车,一会你就会发现visual studio 2017已经恢复为最初状态了

前言

在使用microsoft visual studio的过程中,经常由于自己的一些sao操作,把窗口、字体、快捷键搞乱,怎么将microsoft visual studio恢复默认设置呢?其实很简单,那么今天小编就和大家一起分享将microsoft visual studio恢复默认设置的方法,

一、解决方法

我们在使用 Visual Studio 的时候,常常有一些窗口不见了又弄不回来的情况,如何恢复默认设置呢?

1、点击“开始–>程序–>Microsoft Visual Studio2019–>Tools–>VisualStudio Command Prompt”

2、输入devenv /resetsettings 命令后回车。

3、回车一会儿后,就会恢复VS默认设置。

提示:虽然是以 VS2010为例,但其它版本如 VS2008、VS2012 等也适用,按照上面步骤操作就行了。

二、详细步骤

1.首先,打开microsoft visual studio 2017,选择【工具】

2.在工具菜单中选择 【Visual Studio 命令提示】

3.这时会弹出一个命令提示符窗口,在窗口中输入devenv /resetsettings,回车,一会你就会发现visual studio 2017已经恢复为最初状态了

其他 vs2008~2019都是大同小异

第一次写博客,分享一下最近学到的比较实用的一个功能

最近在使用for循环嵌套的时候发现因其复杂性,我们难以去肉眼debug(除非你脑子是天河二号)而后我了解到VS有他自己的调试系统可以很方便的协助我们去观察语句中变量的改变,以帮助我们debug,接下来我就简单的进行一个绍的介

首先先写一个简单的for循环嵌套

#include

int main()

{

int i, j;

for (i = 1; i <= 9; i++)

{

for (j = 1; j <= 9; j++)

{

printf(" %d%d ", i, j);

}

printf("\n");

}

return 0;

}

执行后得到的结果是

假如我们此时遇到了bug,想要找出问题(或者我们想去更好地理解这串代码)我们可以利用VS的调试功能来逐步执行语句并关注其中变量的变化情况

首先,我们需要在语句中打上断点

只需在任意语句的左侧,及如图所示的小红点一列单击鼠标左键,那么我们就在这个小红点对应的行处打好了断点

接下来选择"调试—开始调试"或者单击F5,我们就可以开始调试了

PS:退出调试快捷键shift+F5

PSS:部分笔记本需要在快捷键中多加一个Fn键

?与往常不同的是此刻我们的代码并不会一口气跑完,而是在断点处停下,像这样

?可见并没有像上次一样输出一堆数字,执行的过程停在了第七行前,并且右侧也没有数字输出

然后就可以发现我们的右上角多了一行按钮

这几个就是我们在调试中会用到的四个玩意儿,从左往右分别是:

“显示下一条语句”、“逐语句”、“逐过程”、“跳出”

由于我这个蒟蒻才学c没多久,目前的编写代码只涉及到单一的函数,所以我只介绍一下“逐语句”(快捷键F11)

注意上上图中的箭头,当我们按下F11后箭头会跳向下一句语句并执行第七行语句,同时我们可以看到在左下角监视窗口内j的值发生了变化(因为执行了第七句,j被赋值)

??

此外,由上图可以发现在刚才发生变化的变量的值被标上了颜色

当我们再次按下F11可以发现输出了“11”(执行了printf)

由此,只要我们继续按下F11,代码就会被一句一句的执行下去,这无疑会对我们的编写带来不小的便利,尤其是像我这种学生党,可以更方便的去理解各种复杂程序

你学废了吗?

PSSS:多打几个断点是个好习惯

前言

要想成为一个合格的程序员,不仅仅要会写代码,更要会调试代码。咔咔一通敲代码,敲出了BUG,这时就分两种程序员,一种是质疑编译器的程序员,“什么?我写出了BUG,是不是机器出了问题?”,然后接着就是迷信式地调试,直至解决BUG。另一种是默默地高效地调试代码,把BUG给修复了。一个合格的程序员不但要会写BUG,还要懂得通过调试来修复BUG,毕竟第一个人想写BUG那是拦都拦不住的。本篇文章案例所使用环境为VS2019。

1.什么是BUG?

bug在英文中的意思是虫子,这又为什么会和计算机程序沾边呢?原来在1947年9月9日,技术员赫柏对继电器编程完毕后,尝试运行,发现继电器无法正常工作。在排查问题后,发现是一只飞蛾飞到了继电器里,触电身亡后,它的尸体导致了机器卡住。 因此在提交错误报告的时候,赫柏直接将飞蛾贴在了报告了,并标了“bug”,从而导致bug有了后面的衍生意。这也是计算机程序的第一个bug。

BUG通常指的是计算机程序程序因为编写错误从而产生的错误以及漏洞。

2.调试的重要性

2.1.什么是调试?

调试(英语:Debugging / Debug),又称排错,是发现和减少计算机程序或电子仪器设备中程序错误的一个过程。

2.2.调试的基本步骤

1、发现程序错误的存在 2、以隔离、消除等方式对错误进行定位 3、确定错误产生的原因 4、提出纠正错误的解决办法 5、对程序错误予以改正,重新测试

程序编写时的常见错误

通常程序的错误分为以下三种:

1、编译型错误 2、链接型错误 3、运行时错误

1、编译型错误:通常是指语法语法出现了问题而产生错误。

2、链接型错误:通常是指标识符名不存在或者拼写错误。

此时编译这段代码,编译器并没有报错。control + F5让代码运行起来。 当代码较多时,不方便一眼看出拼写错误,可以通过control+F 文本查找功能,输入错误的标识符来定位。

3、运行时错误:当编译和运行代码都没有问题时,程序此时运行发生了错误。这也是最难处里的错误。此时就需要借助调试,逐步定位问题。例如:

int main()

{

int i = 0;

int sum = 0;//保存最终结果

int n = 0;

int ret = 1;//保存n的阶乘

scanf("%d", &n);

for(i=1; i<=n; i++)

{

int j = 0;

for(j=1; j<=i; j++)

{

ret *= j;

}

sum += ret;

}

printf("%d\n", sum);

return 0;

}

这个BUG我会在后面进行调试修复的演示。

2.3.debug版本与release版本的介绍

debug版本:通常被称为调试版本。它包含了调试信息,不对程序进行优化,便于程序员调试程序。 release版本:通常被称为发布版本。它不包含调试信息,所以无法进行调试。release版本对程序进行了各种的优化,使得程序的代码大小以及运行速度都是最优的,便于用户的使用。

//本段代码在debug版本与release版本的的代码大小区别

#include int main() { char str[]=“hello world!”; printf(“%s\n”,str); return 0; } debug版本与release版本的exe.文件的大小对比

//本段代码在debug版版本与release版本的区别

#include

int main()

{

int i = 0;

int arr[10] = {0};

for(i=0; i<=12; i++)

{

arr[i] = 0;

printf("hehe\n");

}

return 0;

}

debug版本下程序死循环打印hehe。 release版本下程序并没有死循环打印hehe 这也是说明了程序在release版本下会进行优化。至于为什么在debug版本下会死循环打印hehe呢?首先可以肯定的错误是数组越界访问了,至于为什么会导致程序死循环呢?待会我会对此进行分析。

以上就是release版本与debug版本的一些区别。程序在release版本为什么不能调试?这里我就不做演示,下面将介绍VS2019环境下如何调试。如果你对此感兴趣,不妨在看完下文的介绍后上手试试看看,毕竟实践出真知。

3.VS环境调试介绍

补充:本文使用环境为VS2019。VS环境下,调试的方式和调试的逻辑大同小异。

3.1.环境准备

在当前环境下使用debug模式,这样才能正常的进行调试。

3.2如何开始调试?

开始调试步骤如下: 开始调试后,打开窗口菜单后,如图所示

未开始调试,打开窗口菜单。如图所示 所以进入调试是需要按快捷键或者在调试菜单中单击开始调试(s)进入调试。

3.3学会使用快捷键进行调试

合理的使用快捷键可以大大地提高我们的调试效率,所以学会使用快捷键进行调试是很重要的。 常用的快捷键: F5

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

F9

创建或取消断点。

补充: 断点是在特定点暂停程序执行的特殊标记,使用断点可以检查当前程序状态和行为。断点一旦设置便保留在你的项目中,直到你明确删除它。

F10

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

F11

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

CTRL + F5

开始运行不调试,直接让程序运行起来。如果不想进行调试可以直接使用此快捷键运行程序。

查看更多快捷键

3.4.查看当前程序的信息

3.4.1.查看当前临时程序变量的值

在调试时,观察变量的值的变化。

3.4.2.查看内存信息

通过&取地址操作符,找到变量存放的位置以及存储在内存中的值。

3.4.3.查看调用堆栈

通过调用堆栈,可以清晰的反应函数的调用关系以及当前调用所处的位置。

3.4.4.查看汇编信息

在调试开始之后,有两种方式转到汇编: 方式一:右击鼠标,选择【转到反汇编】: 方法二:在调试菜单中的窗口菜单中:

3.4.5.查看寄存器信息

查看当前的寄存器信息

4.调试问题代码

4.1.例一

int main()

{

int i = 0;

int sum = 0;//保存最终结果

int n = 0;

int ret = 1;//保存n的阶乘

scanf("%d", &n);

for (i = 1; i <= n; i++)

{

int j = 0;

for (j = 1; j <= i; j++)

{

ret *= j;

}

sum += ret;

}

printf("%d\n", sum);

return 0;

}

为什么统计的各个阶乘的和是错的呢? 我们通过调试来看看 通过调试我们发现,当i = 3时,此时ret的值为2,所以才导致求3的阶乘时程序产生了bug。找到了问题,下面是分析该问题,这样每次统计完一个阶乘并把它放入累加的变量中,进入下一次循环前,要把ret的值修改为1,以确保求出阶乘是 正确的。故修改后代码如下

int main()

{

int i = 0;

int sum = 0;//保存最终结果

int n = 0;

int ret = 1;//保存n的阶乘

scanf("%d", &n);

for (i = 1; i <= n; i++)

{

int j = 0;

ret = 1;//每次求n的阶乘将ret的值改成1

for (j = 1; j <= i; j++)

{

ret *= j;

}

sum += ret;

}

printf("%d\n", sum);

return 0;

}

4.2.调试实例例二

//为什么死循环打印hehe?

#include

int main()

{

int i = 0;

int arr[10] = { 0 };

for (i = 0; i <= 12; i++)

{

arr[i] = 0;

printf("hehe\n");

}

return 0;

}

数组越界访问后,这里程序为什么死循环打印hehe呢?调试一下你就知道。 通过监视发现,arr[12]的值随着 i 的值发生变化。 根据查看内存中的地址,可以发现,arr[12]的地址和i的地址是一样的。所以当i = 12进入循环,执行arr[i] = 0;后,i 的值又变成0。循环往复造成程序死循环输出hehe。需要注意的是:这段代码仅在VS2019 X86环境有效。下面我通过画图的方式来演示一下这段代码在内存中的情况。

越界访问会造成程序的错误,我们应该在使用数组的时候检查下标避免越界访问。

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

5.1.什么是优秀的代码?

代码运行正常bug很少效率高可读性高可维护性高注释清晰文档齐全

编写优秀代码技巧

使用assert尽量使用const养成良好的编码风格添加必要的注释避免编码的陷阱。

5.2.优秀编码实例

//模拟实现库函数strlen

size_t my_strlen(const char* str)

{

//断言判断指针有效性

assert(str != NULL);

//记录起始位置

char* start = str;

while(*str++)//str指向的内容不为\0指针++

{

;

}

//通过指针减指针求出字符长度

return str - start - 1;

}

补充:

1、使用断言assert需要包含对应头文件 #include. 2、表达式应注意操作符的优先级问题。 3、通过const来修饰形式参数,保证指针的安全性 4、确定合适的返回类型。因为字符串长度不可能是负数,所以返回类型定义为size_t 5、添加合适的注释

5.3.const修饰指针变量

//const放在*号左边

int main()

{

int num = 10;

int n = 1000;

const int* p = #

*p = 20;//err

p = &n;//ok

return 0;

}

当const放在 * 号左边时,修饰的是指针变量指向的内容,指针变量指向的内容不可以被修改,但是指针变量本身可以被修改。

//const放在 *号右边

int main()

{

int num = 10;

int n = 1000;

int* const p = #

*p = 20;//ok

p = &n;//err

return 0;

}

当const放在 * 号右边时,修饰的是指针变量本身,指针变量不可以被修改,但是指针变量指向的内容可以被修改。

总结

只有多多动手调试,才能够有进步!当遇到bug时,不要再迷信式的调试。我们要尝试通过调试来验证我们的想法是否能够实现。也只有加化自身的调试技巧,才能够让编程之路越走越远。