哈喽各位小伙伴,帅气的我呦呦呦来了哟~
今天我们来介绍一下vs 实用的一些调试技巧.
① F9:设置/取消断点
何所谓断点,就是设置程序执行暂停的点~ 表示程序执行到这里时就会暂停.例如看下面一串代码~
如图所示,我先让光标锁定第九行,当程序执行到这里是就没有往下执行打印"Wyc",而是打印10个呵呵就停止了
这就是F9的功能,设置/取消断点(设置断点后再按一下就取消了)
② F10 逐过程调试
有的小伙伴就问了,既然你说F9是程序运行停止的地方,那么我怎样让程序一步步运行并看到每一步的结果呢,这里就需要用到F10 这个快捷键了,F10 为逐过程调试,按一下执行一句代码,唯一遗憾的是, f10 在遇见函数时,会直接完成函数的调用,而不会进到函数内部细细观察,这也就是逐过程的含义. 为了弥补这个问题,我们迎来一个新的快捷键:F11
③ F11 逐语句调试
这个f11就厉害了,它不会放过任何一句代码,每一句都调试到,非常细致. 那小伙伴们想一想,自定义函数内部是不是也是一句一句的代码呀~ 所以这个快捷键与f10 的区别就是:f11 可以进到函数内部观察,但f10不行.
④ F5: 启动调试,并快速跳到下一个断点处
有的小伙伴可能认为我在对图示代码进行调试的时候是一个一个f10 走到断点处才打印出10个呵呵的,其实不是的,我是用f9设置好断点之后,,直接按了一下f5: 启动调试,并快速让程序执行到断点处(也就是直接跳到断点处,前面的程序被瞬间执行了) 所以那十个hehe 瞬间就打印出来了hhh~
这里需要注意的是:f5 所谓的跳到下一个断点处,指的是跳到下一个逻辑断点,而不是下一个物理断点.
啥意思呢? 我们来看下面一串代码:
如图所示:我在第17 行和第20 行利用f9各设置了一个断点,此时我已经按了一下f5让程序跳到了第一个断点处,此时,如果再按一下f5 会出现什么情况呢? 我按了哈~ 3! 2! 1! 按~
哎呦我的天,这咋回事呀,怎么我按了一下,它没有跳到20行,反而是打印了一个呵呵?
原因已经说过,f5 跳到的是下一个程序执行的逻辑断点,程序在执行完17 行之后,上去之后i++ 再下来执行17行,这时才会再一次在17行的断点处停下,这里是不是就相当于遇到了下一个断点呀~ 所以就产生了没移动但打印了一次的效果 .
⑤ 数组调试
(1) 普通数组观察
来看下面一串代码:
看到这里想必你已经知道,对于普通的一维和二维数组来说,只要在监视窗口中输入它们的数组名,就可以得到它首元素的地址和所有的元素.(对于二维数组arr2来说,它的首元素是arr2[0][0])
(2) 形参数组的观察
在来看下面的一串代码:
而我如果用另外一种表达方式:arr3,10 结果会如何呢?
大家看,当我使用arr3,10 这种表达形式时,就可以访问形参arr3 的所有元素.
同理可得,当我在test1的内部访问arr4的变化时,若要访问它的所有元素,应当使用arr4,3
如图所示;
总结:在数组作为函数形参时,想要在自定义函数的内部访问形参的所有元素,就必须使用
数组名,元素个数 的格式.
需要注意的是,这里的arr3 和arr4 作为形参,必须在各自所对应的函数内部才能访问,否则无法监视它们的变化(这里涉及到栈帧,后期细讲)
⑥ 监视和内存窗口
那有的小伙伴就问了,你这个用来观察的窗口咋打开呀,这个很简单,直接按一下f10 开启逐过程调试
(注;一定要先开启调试再进行下面的操作,不然不会看到监视窗口)
(1) 监视
然后再调试中选择:窗口-->监视(这里一般会看到好几个监视窗口 ,它们是为了便于大量观察数据变化的,如果我们只观察少量数据的变化,只用打开一个窗口就可以啦~) 打开窗口后,在"添加要监视的项"处键入想要观察的数据就行啦~ 变量的话直接键入变量名,如果要取出某一个变量的地址,则只需要在其前面加上& 即可.(这个实际上是取地址操作符,后期细讲~)
(2)内存
那怎样打开内存窗口呢? 也是先f10 启动调试(这里你也可以按其他按键,只要启动调试了就行)
然后同样的,选择:窗口-->内存 就可以啦~
如图所示,像这样,我们就可以看到a在内存中所放的位置和值.你学会了嘛~
⑦ 经典调试案例
明白了上面的知识,我们就来看一下两个经典的调试案例吧~
案例:求1! + 2! + 3! + 4! + 5! + 6! + 7! + 8! + 9! + 10!
要完成这个练习,我们大概是这样一个思路~
第一步:产生1~10 所有的数
第二步:对于每一个数都算出其阶乘,并且每算出一个都把它加到一个初值为0的变量上
第三步:输出这个变量的值.
按照这三步走,我们就有这样一个代码:
运行结果是这个:
这个数字太大了,我们没法判断对错,所以我们换一个小一点的数来试试~
把i的上限改成3,按照代码逻辑,这个结果应该是3的阶乘:也就是1+2+9=12
真的是这样嘛? 我们来看看运行结果~
诶~ 15 ??? 为啥会是15嘞? 哦~,小编一看,这里的ret没有在每一次为一,所以在第二次算完2的阶乘以后,ret中保持的结果为2,所以第三次就是2×1×2×3=12 ,再加上第一次的1! 和第二次的2! 就是12+3=15 你明白了嘛~ 所以为了让每次算出一个数的阶乘后ret回归到1,应该把ret 定义到循环中去,也就变成了下面的代码:
int main()
{
int sum = 0;
for (int i = 1; i <= 10; i++)
{
int ret = 1;
for (int j = 1; j <= i; j++)
{
ret *= j;
}
sum = sum + ret;
}
printf("sum=%d\n", sum);
return 0;
}
你听懂了嘛~,这一期就到这里,下一期再见!
这是这一篇所有的源码~
#include <stdio.h>
int main()
{
for (int i = 0; i < 10; i++)
{
printf("hehe\n");
}
printf("Wyc");
return 0;
}
int main()
{
for (int i = 0; i < 10; i++)
{
printf("hehe\n");
}
printf("helloworld\n");
}
void test(int arr3[])
{
}
void test1(int arr4[][5])
{
}
int main()
{
int arr1[10] = { 0,1,2,3,4,5,6,7,8,9 };
int arr2[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
test(arr1);
test1(arr2);
return 0;
}
int main()
{
int a = 10;
return 0;
}
int main()
{
int ret = 1;
int sum = 0;
for (int i = 1; i <= 3; i++)
{
for (int j = 1; j <= i; j++)
{
ret *= j;
}
sum += ret;
}
printf("%d\n", sum);
return 0;
}
int main()
{
int sum = 0;
for (int i = 1; i <= 10; i++)
{
int ret = 1;
for (int j = 1; j <= i; j++)
{
ret *= j;
}
sum = sum + ret;
}
printf("sum=%d\n", sum);
return 0;
}