一、调试是什么?有多重要?
调试(debug)又称除错,是发现和减少计算机程序或电子仪器设备中程序错误的一个过程
二、debug和release的介绍
三、windows环境调试介绍
①将环境改为Debug
②学会快捷键
F5:

如果想要在断点处设置条件,只有满足条件才会触发断点
右击断点-条件
F10:逐过程,可以是一次函数调用可是一条语句(遇到函数直接跳过)
F11:逐语句,跟F10不同的是,可以进入函数内部(遇到函数会进去函数内部)
ctrl+F5:开始执行不调试,就算打了断点也不会停
在程序执行过程中想要观察程序的上下文的环境的相关数据(例如定义了一个变量a,a在运行过程中的变化情况),在调试(运行)之后,点击窗口
重点:监视、调用堆栈、内存、反汇编、寄存器
监视:可自己添加删除自己想监控的元素
注:如果在函数中传入数组,这时候如果想监视这个数组,上面只会显示数组中的第一个元素,如果想要显示自定义的数组范围:数组名+,+范围,例:
内存:如果想要看a在内存里面的位置,在地址里面输入&a,回车就出现下面场景
如果要看arr,在地址里面输入&arr,回车
反汇编:观察代码翻译为汇编代码是什么样的
寄存器: 可以观察代码在运行中观察寄存器的值,当然如果你知道寄存器的名字,可以在监视中观察
调用堆栈:
在数据结构中:栈:先进后出 队列:先进先出
局部变量是放在内存中的栈区的
栈区的使用习惯是先试用高地址的空间再使用地地址的空间
四、如何写好(易于调试)的代码
常见的coding技巧 :
-
使用assert
-
尽量使用const
-
养成良好的编码风格
-
添加必要的注释
-
避免编码的陷阱
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "hello";
char arr2[20] = { 0 };
strcpy(arr2, arr1);
printf("%s", arr2);
return 0;
}
自己写:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
void my_strcpy(char* dest, char* src)
{
while (*src != '\0')
{
*dest = *src;
dest++;
src++;
}
*dest = *src;//把\0拷贝过去
}
int main()
{
char arr1[] = "hello";
char arr2[20] = { 0 };
my_strcpy(arr2, arr1);
printf("%s", arr2);
return 0;
}
这个代码可以发挥作用,但是不够好,接下来做一些优化
while (*dest++ = *src++)//只要src指向的内容不是0,循环就不会停止,即做到了拷贝又做到遇到\0停下来
;//改为后置++,先赋值后++
断言:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
void my_strcpy(char* dest, char* src)
{
assert(src != NULL||dest!=NULL);
while (*dest++ = *src++)//只要src指向的内容不是0,循环就不会停止,即做到了拷贝又做到遇到\0停下来
;//改为后置++,先赋值后++
}
int main()
{
char arr1[] = "hello";
char arr2[20] = { 0 };
my_strcpy(arr2, arr1);
printf("%s", arr2);
return 0;
}
if (src == NULL || dest == NULL)
{
return;
}
每次进入函数内部都要判断一次,如何更高效?用assert(需要包含头文件assert.h),里面可以放一个表达式,如果表达式的结构为假,就报错,如果为真啥事都不发生
但是在Release版本中优化掉了
const
const修饰指针变量的时候放在*左边时,修饰指针指向的内容,*p不能改但是p可以改(const int *p)
const修饰指针变量的时候放在*右边时,修饰的指针变量本身,*p能改但是p不可以改(int *const p)