网站建设一条网站设计网页首页介绍
- 作者: 五速梦信息网
- 时间: 2026年04月20日 07:43
当前位置: 首页 > news >正文
网站建设一条,网站设计网页首页介绍,电商平台有哪些平台,西瓜编程网站怎么做目录#xff1a; 1.什么是bug#xff1f; 2.调试是什么#xff1f;有多重要#xff1f; 3.debug和release的介绍 4.Windows环境调试介绍 5.一些调试的实例 6.如何写出好(易于调试)的代码 7.编程常见的错误 1.什么是bug#xff1f; bug—臭虫、虫子。 为什么含…目录 1.什么是bug 2.调试是什么有多重要 3.debug和release的介绍 4.Windows环境调试介绍 5.一些调试的实例 6.如何写出好(易于调试)的代码 7.编程常见的错误 1.什么是bug bug—臭虫、虫子。 为什么含义是臭虫、虫子呢 答案是第一次被发现的导致计算机错误的是一只飞蛾也是第一个计算机程序的错误。 2.调试是什么有多重要 前言 所有发生的事情都一定有迹可循如果问心无愧就不需要掩盖也就没有迹象了如果问心有愧就必然需要掩盖那就一定会有迹象迹象越多就越容易顺藤而上这就是推理的途径。 顺着这条途径顺流而下就是犯罪逆流而上就是真相。 一名优秀的程序员都是一名出色的侦探。 每一次调试都是尝试破案的过程。 2.1调试是什么 调试(英语Debugging/Debug),又称除错是发现和减少计算机或电子仪器设备中程序错误的一个过程。 2.2调试的基本步骤 ①发现程序错误的存在 ②以隔离、消除等方式对错误进行定位 ③确定错误产生的原因 ④提出纠正错误的解决办法 ⑤对程序错误予以改正重新测试 2.3Debeg和Release的介绍 Debug通常称为调试版本它包含调试信息并且不做任何优化便于程序员调试程序。 Release称为发布版本它往往是进行了各种优化使得程序在代码大小和运行速度上都是最优的以便用户很好地使用。 1在VS2019中如何转换 2Release对代码大小上是最优的 代码 #includestdio.h//自定义函数——实现对整数数组的冒泡排序 void bubble_sort(int* str, int sz) {//趟数int i 0;for (i 0; i sz - 1; i){//一趟冒泡排序的过程int j 0;for (j 0; j sz - 1 - i; j){//升序if (str[j] str[j 1]){int tmp str[j];str[j] str[j 1];str[j 1] tmp;}}} }int main() {int arr[] { 10,9,8,7,5,6,4,1,2,3 };//定义整形数组并初始化int sz sizeof(arr) / sizeof(arr[0]);//计算数组的大小//调用函数实现升序bubble_sort(arr, sz);//输出升序后的数组int i 0;//循环变量for (i 0; i sz; i){printf(%d , arr[i]);}printf(\n);return 0; }观察分别在Debeg和Release环境下生成的可执行程序的大小 3Release对代码运行速度上是最优的 代码 #include stdio.h int main() {int i 0;//数组下标界限0~9int arr[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };for (i 0; i 12; i){//数组下标为10~12时数组越界arr[i] 0;printf(hehe\n);}return 0; } 在Debeg和环境下该代码死循环解释在调试的实例二。 在Release环境下该代码打印13次hehe不死循环因为编译器优化把i的地址放在数组arr地址的下面了。 3.Windows环境调试介绍 3.1调试环境的准备 在环境中选择debug选项才能使代码正常调试。 3.2学会快捷键 最常使用的几个快捷键 F5 启动调试经常用来直接跳到下一个断点处。 F9 创建断点和取消断点。 断点的重要作用可以在程序的任意位置设置断点。这样就可以使得程序在想要的位置停止执行继而一步步执行下来。 F5和F9常配合使用F5一般不会单独使用的。断点再多文件、多代码中常用。 F10 逐过程通常用来处理一个过程一个过程可以是一次函数调用或者是一条语句。 F11 逐语句就是每次都执行一条语句但是这个快捷键可以使我们的执行逻辑进入函数内部(这是最常用的)。 ctrl F5 开始执行不调试。如果你想让程序直接运行起来而不调试就可以直接使用。 3.3调试的时候查看程序当前信息 注意只有先F10开始调试才能看到程序当前信息。 3.3.1查看临时变量的值 在调试开始之后用于观察变量的值。 3.3.2查看内存信息 在F10调试开始之后用于观察内存信息。 3.3.3查看汇编信息 在F10调试开始之后有两种方式转到汇编。 1第一种方式右击鼠标选择[转到汇编] 2第二种方式 可以切换到汇编。 3.3.4查看寄存器信息 在F10调试起来之后有两种方式观察寄存器信息。 1第一种方式 2知道寄存器的名字可以在监视中观察寄存器信息。 可以查看当前运行环境的寄存器的使用信息。 3.3.5查看调用堆栈 在F10调试之后可以观察调用堆栈。 通过调用堆栈可以清晰的反应函数的调用关系以及当前调用所处的位置。 4.多多动手尝试调试才能有进步 ①一定要熟练掌握调试技巧 ②初学者可能80%的时间在写代码20%的时间在调试。但是一个程序员可能20%的时间在写代码但是80%的时间在调试。 ③我们现在所讲的都是一些简单的调试以后可能会出现很复杂的调试场景:多线程程序的调试等。 ④多多使用快捷键提升效率。 5.一些调试的实例 实例一 实现代码求 123 … n! 不考虑溢出。 代码1实现阶乘 #includestdio.hint main() {//输入求几的阶乘int n 0;scanf(%d, n);//实现求n! n!n*(n-1)int ret 0;int i 0;for (i 1; i n; i){ret * i;}//输出结果printf(%d\n, ret);return 0; } 如果我们输入3想输出6但实际输出的是0. why 这里我们就得找我们的问题 ①首先通过经验推测问题出现的原因初步确定问题可能的原因最好。 ②实际上手调试很有必要。 ③调试的时候我们要心里有数。 通过初步推测ret变量有问题我们在在for循环打断点调试观察变量ret具体有什么问题。 代码2 求 123 … n! #includestdio.hint main() {//输入有n个阶乘int n 0;scanf(%d, n);//循环 求 123 … n! int ret 1;int i 0;int sum 0;//存放阶乘的累加和for (i 1; i n; i){int j 0;//实现求i的阶乘for (j 1; j i; j){ret * j;}sum ret;}//输出结果printf(%d\n, sum);return 0; }如果我们输入3想输出9但实际输出15。 why 分析推测循环出错了第一次调试在第二个循环处打断点一步步调试监视变量的变化。 但是没有发现是哪里错了第二次调试在断点处右击设置断点条件快速调试到错误处符合断点条件就停止再F10观察具体原因。 实例二 #include stdio.h int main() {int i 0;//数组下标界限0~9int arr[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };for (i 0; i 12; i){//数组下标为10~12时数组越界arr[i] 0;printf(hehe\n);}return 0; } 数组越界应该是程序错误不执行但是我们运行后发现程序死循环了。 why 我们F10调试起来观察变量。 在调试的时候我们发现每一次i的值都和arr[12]的值一样当arr[12]0时i也变成0了所以死循环。 那arr[12]和i是不是地址一样我们调试观察之后确实是一样的。 图解 在i和arr数组中间恰好就是2个整形吗 答不一定该代码只是在VS2019 X86环境下实验的结果。 如果是VC6.0——i和arr之间没有多余的空间gcc——i和arr之间有一个整形空间。 所以说平时我们写代码要注意不数组越界了。 6.如何写出好易于调试的代码 6.1优秀的代码 ①代码运行正常 ②bug很少 ③效率高 ④可读性高(如良好的代码风格函数名、变量名见名知意等) ⑤可维护性高 ⑥注释清晰 ⑦文档齐全 常见的coding技巧 ①使用assert ②尽量使用const ③养成良好的编码风格 ④添加必要的注释 ⑤避免编码的陷阱 6.2示范 模拟实现库函数strcpy strcpy 1.函数原型 2.函数功能 3.函数参数 4.函数的返回类型 代码1模拟实现strcpy 分析 #includestdio.h #includestring.h//自定义strcpy//代码1 void my_strcpy(char* dest, const char* src) {//拷贝\0之前的字符while (*src ! \0){*dest *src;dest;src;}//拷贝\0*dest src; } int main() {//将arr2中的字符串拷贝在arr1char arr1[20] #############;char arr2[] hello;//调用库函数实现//strcpy(arr1, arr2);//调用自定义函数实现my_strcpy(arr1, arr2);//打印拷贝后的arr1printf(%s\n, arr1);return 0; } 代码2优化函数体 #includestdio.h #includeassert.h//自定义strcpy//代码2 void my_strcpy(char dest, const char* src) {//优化1使用指针之前一定要检查是否有效如果无效就报错//assert–断言// assert中可以放一个表达式表达式结果为假就报错为真就啥事都不发生正常运行//assert的头文件是assert.h//assert其实在release版本中被优化调了assert(dest src);//断言指针的有效性//优化2使代码简化//*dest *src;//等价于//*dest *src;//dest;src;while (*dest src)//\0的ASCII码值就是0所以拷贝到\0停止{;} } int main() {//将p中的字符串拷贝在arr1char arr1[20] #############;char p NULL;//调用自定义函数实现my_strcpy(arr1, p);//打印拷贝后的arr1printf(%s\n, arr1);return 0; }程序结果 代码3优化函数的形参 如下代码我们程序不报错但是没有成功完成我们想要的拷贝 #includestdio.h #includeassert.hvoid my_strcpy(char* dest, char* src) {assert(dest src);//断言指针的有效性while(*src dest)//程序员喝酒写反了这样我们没有实现拷贝的目的{;}//将src所指向内容拷贝到dest所指向数组 }int main() {char arr[20] #############;char arr1[20] hello;my_strcpy(arr, arr1);printf(%s\n, arr);return 0; } 该怎么避免出现这种错误呢 我们先来学习const的作用 #include stdio.hvoid test() {//代码1//定义两个整型变量int n 10;int m 20;//没有const修饰int p n;//可以通过指针变量p将指针所指向的内容n的值改成20p 20;//ok//可以修改指针变量本身p m; //ok } void test1() {//代码2const int num 10;//num 20;//err,因为num被const修饰所以不能修改//但是通过指针变量pnum能被修改了(p就像卖票的黄牛一样)int p num;*p 20; } void test2() {//代码3int n 10;int m 20;//const放在的左边const int p n;//也可写成int const* p n;//*p 20;//err,因为const修饰的指针p指向的内容所以不能通过指针来修改p m; //ok因为const只修饰的是指针p指向的内容所以指针变量本身可以修改 } void test3() {//代码4int n 10;int m 20;//const放在的右边int const p n;*p 20; //ok因为const只修饰的是指针变量本身所以指针指向的内容可以通过指针改变//p m; //err,因为const修饰的是指针变量本身所以指针变量本身不能被修改 } int main() {//测试无cosnt的test();//测试const修饰变量test1();//测试const放在*的左边test2();//测试const放在*的右边test3();return 0; } 结论 const修饰指针变量的时候 1.const如果放在*的左边const修饰的是指针指向的内容保证指针指向的内容不能通过指针来改变但是指针变量本身可以修改。 2.const如果放在*的右边const修饰的是指针变量本身保证指针变量本身的内容不能被修改但是指针指向的内容可以通过指针来改变。 3.const就像法律不能被修改。 学习了const的作用我们来修改刚在代码的问题可以运行但是没有完成拷贝是因为*dest和src写反了因为src所指向的内容不变。所以我们可以在把第二个形参改成const int src,用const修饰指针指向的内容这样的话如果不小心将*dest和src写反直接就编译错误不会运行成功很快就发现代码的错误了。 #includestdio.h #includeassert.hvoid my_strcpy(char dest,const char* src) {assert(dest src);//断言指针的有效性while (*src dest)//程序员喝酒写反了这样我们没有实现拷贝的目的{;}//将src所指向内容拷贝到dest所指向数组 }int main() {char arr[20] #############;char arr1[20] hello;my_strcpy(arr, arr1);printf(%s\n, arr);return 0; } 如下图 代码4优化函数的返回类型最终的优化版本 #includestdio.h #includeassert.h//库函数strcpy的返回值是目的地的起始地址 char my_strcpy(char* dest,const char* src) {assert(dest src);//断言指针的有效性char* ret dest;//存放目的地的起始地址while (*dest src){;}//将src所指向内容拷贝到dest所指向数组return ret; }int main() {char arr[20] #############;char arr1[20] hello;//优点链式访问有返回值才可以printf(%s\n, my_strcpy(arr, arr1));return 0; }运行结果 练习模拟strlen #includestdio.h #includeassert.h//size_t是unsigned int的别名因为长度没有负数 size_t my_strlen(const char str) {assert(str ! NULL);//断言指针的有效性size_t count 0;//计数while (*str){count;}return count; }int main() {char arr[] abcdef;printf(%d\n, my_strlen(arr));return 0; } 7.编程常见的错误 7.1编译型错误语法错误 直接看错误提示信息双击锁定解决问题。或者凭借经验就可以搞定相对来说简单。 7.2链接型错误 看错误提示信息主要在代码中找到错误信息中的标识符然后定位问题所在。一般是标识符名不存在或者拼写错误。 类型1库函数不包含头文件 类型2拼写错误 我们怎么找到错误位置 7.3运行时错误编译、链接都没错但是运行结果有问题 借助调试逐步定位问题最难搞。 最后温馨提示 做一个有心人积累排错经验
- 上一篇: 网站建设一年600网络推广方式有哪些推广思路
- 下一篇: 网站建设移动端官网乐清做网站哪家好
相关文章
-
网站建设一年600网络推广方式有哪些推广思路
网站建设一年600网络推广方式有哪些推广思路
- 技术栈
- 2026年04月20日
-
网站建设一秒互联wordpress相册设置
网站建设一秒互联wordpress相册设置
- 技术栈
- 2026年04月20日
-
网站建设一龙条seo站群系统
网站建设一龙条seo站群系统
- 技术栈
- 2026年04月20日
-
网站建设移动端官网乐清做网站哪家好
网站建设移动端官网乐清做网站哪家好
- 技术栈
- 2026年04月20日
-
网站建设颐高上海街网站建设代码标签大全
网站建设颐高上海街网站建设代码标签大全
- 技术栈
- 2026年04月20日
-
网站建设以及运营方面wordpress物体替换纹理
网站建设以及运营方面wordpress物体替换纹理
- 技术栈
- 2026年04月20日
