商丘建设网站,做网站要执照吗,网站建设字体,wordpress安装install目录 一、什么是bug?
二、调试
1.一般调试的步骤
2.Debug 和 Release
三、调试环境准备 四、调试时要查看的信息
1.查看临时变量的值
2.查看内存信息 3.查看调用堆栈 4.查看反汇编信息
5.查看寄存器
五、练习
六、常见的coding技巧
七、const的作用
八、编程常见…目录 一、什么是bug?
二、调试
1.一般调试的步骤
2.Debug 和 Release
三、调试环境准备 四、调试时要查看的信息
1.查看临时变量的值
2.查看内存信息 3.查看调用堆栈 4.查看反汇编信息
5.查看寄存器
五、练习
六、常见的coding技巧
七、const的作用
八、编程常见的错误 一、什么是bug?
我们平时会口头说 bug ,报错waring(报警)等,bug 英文的意思是虫子然而在计算机发展史上的第一只 Bug 真的是因为一只飞蛾意外走入一电脑而引致故障因此Bug从原意为臭虫引申为程序错误。
当我们 这个时候就需要我们的调试 来开启新大陆
关于程序错误的 参考资料
二、调试
平时敲代码总会遇到与一些问题导致程序执行不过去你可能在那一直盯着刚写完的代码看心里想这到底哪里出错了但是就是没有找打错误的原因这时就需要我们平时了解到的调试来解决问题(起先使用可能不熟练慢慢来)
调试英语Debugging / Debug又称除错是发现和减少计算机程序或电子仪器设备中程序错误的一个过程
1.一般调试的步骤
发现程序错误的存在以隔离、消除等方式对错误进行定位确定错误产生的原因提出纠正错误的解决办法对程序错误予以改正重新测试
2.Debug 和 Release Debug 通常称为调试版本它包含调试信息并且不作任何优化便于程序员调试程序。 Release 称为发布版本它往往是进行了各种优化使得程序在代码大小和运行速度上都是最优的以便用户很好地使用。 接下来调试下方代码
#includestdio.h
int main()
{char* p hello word!;printf(%s\n,p);return 0;
}
在debug版本下 执行程序文件名.exe 是几十KB
而在release版本下 是 几 KB(原因是代码大小和运行速度上都是最优的)
再看下方代码
#includestdio.h
int main()
{int i 0;int arr[10] { 0 };for (i 0; i 12;i){arr[i] 0;printf(haha\n);}return 0;
}
在 vs2022 x86 debug 的环境下
该程序的【执行结果】 无限循环打印 haha
而在release版本下 没有死循环 打印了13行的haha
二者区别是因为变量在内存中开辟的顺序发生了变化影响到了程序执行的结果
三、调试环境准备 如果要对代码进行调试首先要准备好调试的环境
就是要在debug版本下才能使代码正常调试
点击开始调试或者按F5 在这里介绍一些调试的快捷键
F5 启动调试经常用来直接跳到下一个断点处 F9 创建断点和取消断点。 断点的重要作用可以在程序的任意位置设置断点。 这样就可以使得程序在想要的位置随意停止执行继而一步步执行下去F11 逐语句就是每次都执行一条语句但是这个快捷键可以使我们的执行逻辑进入函数内部这是最长用的F10 逐过程通常用来处理一个过程一个过程可以是一次函数调用或者是一条语句Ctrl F5 开始执行不调试如果你想让程序直接运行起来而不调试就可以直接使用
其他快捷键 四、调试时要查看的信息
1.查看临时变量的值
在按调试后观察变量的值 例如 输入 i 一直按F11当 i 的值变为 11时 i值的变化0-11 2.查看内存信息 在内存窗口 输入 i(找到i 的内存地址) 3.查看调用堆栈
反映的是调用逻辑 4.查看反汇编信息 5.查看寄存器 五、练习
【例 1】
//实现代码求 123 ... n! 不考虑溢出
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;
} 输入 1输入2 和我们预想的结果一样但当我们输入 3 的时候结果应该是 9 实际输出结果为 打印的结果出错了
接着进行调试当调试到 i 2是 正常的 调试到 j 3 是 ret 应该是 6 但是发现 ret由4 变到 12 经果分析我们发现 原来是ret 每次进入内层的for循环 ret 的值接着上次的执行结果继续算
这时 我们在内层for循环上方加上 ret 1;
//实现代码求 123 ... n! 不考虑溢出
#includestdio.h
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;//添加的代码for (j 1; j i; j){ret * j;}sum ret;}printf(%d\n, sum);return 0;
} 【例 2 】死循环的原因
#includestdio.h
int main()
{int i 0;int arr[10] { 0 };for (i 0; i 12;i){arr[i] 0;printf(haha\n);}return 0;
}
调试后发现 六、常见的coding技巧
使用assert断言是一个宏在release版本中会自动优化掉尽量使用const下面会讲到用法 养成良好的编码风格添加必要的注释避免编码的陷阱
【例】模拟实现库函数strcpy、
库函数strcpy //模拟实现strcpy
#includestdio.h
#includeassert.h
char* my_strcpy(char *des,const char *src)
{assert(des ! NULL);assert(src ! NULL);//避免字符串为空char* temp des;while (*des){*des *src;des;src;}return (temp);
}
int main()
{char* str ab;char arr[20] xxxxxxxxxx;printf(%s\n,my_strcpy(arr,str));return 0;
}
优化
#includestdio.h
#includeassert.h
char* my_strcpy(char* des,const char *src)
{assert(des ! NULL);assert(src ! NULL);char* temp des;//用于返回首元素地址while (*temp *src);return des;
}
int main()
{char *arr1 abcdef;char* arr2[20] {0};printf(%s\n,my_strcpy(arr2,arr1));return 0;
}
七、const的作用
const 在 * 左边
int num 0;
int n 0;
const int *p num;
p n; //ok
*p 20; //error const 在 * 右边
int n 1000;
int num 0;
int * const p num; //限制了指针变量本身
p n; //error
*p 20;//ok 【小总结】
const 修饰指针变量的时候
const放在 * 左边修饰的是指针指向的内容保证指针指向的内容不被修改。但是指针变量可以修改const 放在* 右边修饰的是指针变量本身保证指针变量本身不被修改。但是可以修改指针指向的内容
练习模拟实现strlen
//模拟实现strlen
#includestdio.h
#includeassert.h
int my_strlen(const char* str)
{assert(str ! NULL);int count 0;while (*str) {count;str;}return count;
}
int main()
{char* str abcdefg;printf(%d\n,my_strlen(str));return 0;
}
八、编程常见的错误 编译型错误
直接看错误提示信息双击解决问题。或者凭借经验就可以搞定
链接型错误
看错误提示信息主要在代码中找到错误信息中的标识符然后定位问题所在。一般是标识符名不 存在或者拼写错误
运行时错误
借助调试逐步定位问题。