c语言有这个就够了七.实用调试技巧

author author     2022-12-05     491

关键词:

(一)什么是BUG

历史上第一个bug

【C语言有这个就够了】七.实用调试技巧_调试

导致程序运行错误的对象

(二)调试是什么

调试就是破案的过程,因为有人写代码是这样的:

【C语言有这个就够了】七.实用调试技巧_优秀代码_02

1.调试

又称除错,是发现和减少计算机程序或电子仪器设备中程序错误的一个过程。


2.调试的基本步骤

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

3.debug和release的介绍

debug称为调试版本,它包含调试信息,且不做任何优化,便于存程序员调试程序

【C语言有这个就够了】七.实用调试技巧_调试_03

release称为发布版本,它往往是进行了各种优化,使程序在代码大小和运行速度上都是最优的,以便用户使用

【C语言有这个就够了】七.实用调试技巧_优秀代码_04

我们可以看到,同一个代码,在不同版本下,内存大小不同。

同样对于这个代码:

#include <stdio.h>
int main()

int i = 0;
int arr[10] = 0 ;
for (i = 0; i <= 12; i++)

arr[i] = 0;
printf("gaga\\n");

return 0;

【C语言有这个就够了】七.实用调试技巧_解决bug_05

【C语言有这个就够了】七.实用调试技巧_解决bug_06

如果是 debug 模式去编译,程序的结果是死循环;

如果是 release 模式去编译,程序没有死循环;

这样看来,release的确会优化。

(三) Windows环境调试介绍

1.准备

选择debug模式

2.快捷键

2.1 F5

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

注:F5通常与F9配合使用(在代码错误处用F9设置断点,用F5直接跳到断点处)

2.2 F9

创建断点和取消断点(代码执行到断点处停下来)

断点的重要作用,可以在程序的任意位置设置断点。

这样就可以使得程序在想要的位置随意停止执行,继而一步步执行下去


2.3 F10

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


2.4 F11

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

3.调试的时候查看程序当前信息

【C语言有这个就够了】七.实用调试技巧_调试_07

合理运用,可以更快找出bug。

(四) 一些调试的实例

1.实现代码:求 1!+2!+3! ...+ 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;

【C语言有这个就够了】七.实用调试技巧_调试_08

我们发现i=3时,ret为12,结果错误;

仔细分析,发现ret未初始化;

在​​ int j=0;​​​前增加​​ret=1;​

2.研究程序死循环的原因

#include <stdio.h>
int main()

int i = 0;
int arr[10]=1,2,3,4,5,6,7,8,9,10;
for (i = 0; i <= 12; i++)

arr[i] = 0;
printf("gaga\\n");

return 0;

1.栈区的默认使用规则:

先使用高地址处的空间

再使用低地址处的空间

2.数组随着下标的增长,地址由低到高变化

【C语言有这个就够了】七.实用调试技巧_调试_09

3.过程中数组越界可能可能遇到i,在越界改变时可能把i变为0,导致程序死循环

【C语言有这个就够了】七.实用调试技巧_优秀代码_10

(五)如何写出好代码

1.优秀的代码

代码运行正常

 bug很少

 效率高

 可读性高

 可维护性高

 注释清晰

 文档齐全

2.技巧

使用assert

尽量使用const

养成良好的编码风格

添加必要的注释

避免编码的陷阱

3.案例模拟实现strcpy

#include<stdio.h>
int main()

char arr1[] = "#########";
char arr2[] = "ajfhk";
strcpy(arr1, arr2);
printf("%s\\n", arr1);
return 0;

【C语言有这个就够了】七.实用调试技巧_解决bug_11

那为什么没有打印后面的#######?

通过调试发现:

【C语言有这个就够了】七.实用调试技巧_解决bug_12

拷贝了一个\\0过去,打印时遇到\\0停止

自己的strcpy

5分

#include<stdio.h>
void my_strcpy(char* dest, char* src)

while (*src != \\0)

*dest = *src;
src++;
dest++;

*dest = *src;//0

int main()

char arr1[] = "#########";
char arr2[] = "ajfhk";
my_strcpy(arr1, arr2);
printf("%s\\n", arr1);
return 0;


6分

#include<stdio.h>
void my_strcpy(char* dest, char* src)

while (*dest++ = *src++)

;



int main()

char arr1[] = "#########";
char arr2[] = "ajfhk";
my_strcpy(arr1, arr2);
printf("%s\\n", arr1);
return 0;


7分

#include<stdio.h>

void my_strcpy(char* dest, char* src)

if (dest != NULL && src != NULL)

while (*dest++ = *src++)

;




int main()

char arr1[] = "#########";
char arr2[] = "ajfhk";
my_strcpy(arr1, arr2);
printf("%s\\n", arr1);
return 0;

防止输入为NULL的时候,整个程序崩盘;但这种更改方式也没有进行拷贝,而且没提示;


8分

#include<stdio.h>
#include<assert.h>
void my_strcpy(char* dest, char* src)

assert(dest != NULL);//断言
assert(src != NULL);
while (*dest++ = *src++)

;



int main()

char arr1[] = "#########";
char arr2[] = "ajfhk";
my_strcpy(arr1, arr2);
printf("%s\\n", arr1);
return 0;

通过assert判断,并且及时报错

但是,当程序员写反时*src++=*dest++,依然有可能运行成功(只要arr1<arr2)

#include<stdio.h>
#include<assert.h>
void my_strcpy(char* dest, char* src)

assert(dest != NULL);
assert(src != NULL);
while (*src++=*dest++)

;



int main()

char arr1[] = "#####";
char arr2[] = "ajfhk";
my_strcpy(arr1, arr2);
printf("%s\\n", arr1);
return 0;

【C语言有这个就够了】七.实用调试技巧_调试_13

9分

#include<stdio.h>
#include<assert.h>
void my_strcpy(char* dest, const char* src)//加上const,反了会报错。

assert(dest != NULL);
assert(src != NULL);
while (*dest++ = *src++)

;



int main()

char arr1[] = "#####";
char arr2[] = "ajfhk";
my_strcpy(arr1, arr2);
printf("%s\\n", arr1);
return 0;

const使变量不能改变,注意

#include<stdio.h>
int main()

const int num = 10;
int* p = &num;
*p = 20;
printf("%d\\n", num);
return 0;

这里p改变了一个我们主观上不想改变的值,

#include<stdio.h>
int main()

const int num = 10;
int n=100;
const int* p = &num;//即使写错了,也能报错
//const放在*左边时,修饰*p,也就是说:不能通过p来改变*p(num)的值
*p = 20;
printf("%d\\n", num);
return 0;
#include<stdio.h>
int main()

const int num = 10;
int*const p = &num;
//const放在*右边时,修饰p,也就是说:不能改变p的值
*p = 20;
int n=10;
p=&n;
printf("%d\\n", num);
return 0;


10分

#include<stdio.h>
#include<assert.h>
char*my_strcpy(char* dest, const char* src)//加上const,反了会报错。

char*ret=dest;
assert(dest != NULL);
assert(src != NULL);
while (*dest++ = *src++)//把src指向的字符串拷贝到dest指向的字符串,包含\\0

;

return ret;


int main()

char arr1[] = "#####";
char arr2[] = "ajfhk";
printf("%s\\n",my_strcpy(arr1, arr2));//返回值时另一个函数的参数
return 0;

4.案例模拟实现strlen

#include<stdio.h>
#include<assert.h>

int my_strlen(const char* str)//*str指向的内容不会被改变,但是指针的位置可以改变

int count = 0;
assert(str != NULL);
while (* str != \\0)

count++;
str++;

return count;


int main()

char arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\\n", len);
return 0;

​(七)编程常见的错误

1.编译型错误

直接看错误提示信息(双击),解决问题。或者凭借经验就可以搞定。相对来说简单。

2.链接型错误

看错误提示信息,主要在代码中找到错误信息中的标识符,然后定位问题所在。一般是标识符名不

存在或者拼写错误。

3.运行时错误

借助调试,逐步定位问题,最难搞。



c语言有这个就够了四.操作符详解

(七)关系操作符​​< <= > >= != ==​​都挺简单,唯一注意=和==(八)逻辑操作符逻辑与 &&逻辑或 ||#include<stdio.h>intmain()inta=9;intb=1;intc=0;printf("%d\\n",a&b);printf(" 查看详情

c语言有这个就够了四.操作符详解

(一)操作符分类算术操作符;移位操作符;位操作符;赋值操作符;单目操作符;关系操作符;逻辑操作符;条件操作符;逗号表达式;下标引用,函数调用和结构成员。(二)算术操作符+-*/%1./操作符的两个操作数都是整数... 查看详情

vs环境——c语言实用调试技巧(代码片段)

目录什么是bug?调试的目的调试的基本步骤Debug和Release的介绍windows环境调试介绍 1.选择Debug调试版本 2.学会快捷键 3.调试窗口的使用 1.局部变量窗口  2.监视窗口 3.内存查看窗口 4.调用堆栈窗口什么是bug?bug是计算... 查看详情

c语言进阶学习笔记七程序执行+调试技巧(实用技巧篇)(代码片段)

文章目录一、程序执行篇①预处理详解②宏定义③define标识符字符串④define宏名(参数表)字符串⑤宏和函数对比二、调试技巧篇①什么是bug?②调试是什么?有多重要?③debug和release的介绍④windows环境调试介绍⑥如何写出... 查看详情

3星|《好文案一句话就够了》:10年前一些日本经典广告文案

...的经典广告文案,毕竟是翻译过来的,一部分涉及到日本语言文化可能难以体现原文的妙处,前半部分的案例还是浅显直白看起来没障碍也感觉确实不错。作者整理的文案技巧看着都眼熟,没发现有创新。具体的技巧清单可以参... 查看详情

c语言这一张图就够了!!!

思维导图,原文件更详细,需要的私信我哦!!! 查看详情

考试c语言,指针不会?看这一篇博客就够了(代码片段)

文章目录C语言指针1.普通指针1.1指针的定义1.2指针实例理解1.3头脑风暴1.4头脑风暴(二)1.5二级指针1.7指针常量1.8常量指针2.数组指针/指针数组2.1数组的理解2.2数组强制类型和下标2.3数组指针2.4指针数组3.函数指针3.1函数... 查看详情

c语言入门到精通,这一篇就够了(13万字笔记)(代码片段)

...情提示:先关注收藏,再查看,13万字保姆级C语言从入门到精通教程。文章目录计算机常识什么是计算机程序?什么是计算机语言?常见的计算机语言类型有哪些?什么是C语言?C语言历史C语言标准C语言现状为什么要学习C... 查看详情

了解kotlin,看这个就够了

在这本书中,我会使用Kotlin作为主要的语言来开发一个android应用。方式是通过开发一个应用来学习这门语言,而不是根据传统的结构来学习。我会在感兴趣的点停下来通过与Java1.7对比的方式讲讲Kotlin的一些概念和特性。用这种... 查看详情

想要了解kotlin,看这个就够了

在这本书中,我会使用Kotlin作为主要的语言来开发一个android应用。方式是通过开发一个应用来学习这门语言,而不是根据传统的结构来学习。我会在感兴趣的点停下来通过与Java1.7对比的方式讲讲Kotlin的一些概念和特性。用这种... 查看详情

c语言基础知识入门这一篇就够了(代码片段)

一、c语言基础知识入门hello,world,你好编程!#include<stdio.h> intmain()  /*在双引号中间输入HelloWorld*/   printf("HelloWorld");  return0; 注:在最新的C语言的标准中,main主函数前的类型为int而不是void!&#x... 查看详情

c语言_7运算符!看这篇就够了

一、算术运算符1.加法运算符+#include<stdio.h>intmain()inta=2;intb=3;printf("a+b=%d\\n",a+b);return0;运行结果:2.减法运算符-#include<stdio.h>intmain()inta=4;intb=3;printf("a-b=%d\\n",a-b);return0;运行结果:3.乘法运算符*#in 查看详情

学习go语言一篇就够了(持续更新)(代码片段)

前言:写博客也写了差不多一年了,我更多的时候是记录自己学习的情况,有时也有自己工作上遇到的bug,自己有时候也比较迷茫,不知道怎么去写博文,我也很想别人跟我提提建议,但是有时候觉得写写博客还是很有成就感的,我有时候... 查看详情

08实用调试技巧(代码片段)

到这一章节,C语言初阶的基础知识基本完结,那么我们已经具备了基础的代码编程能力,还需要在牛客,LeetCode,PTA,洛谷等平台刷题训练,或参加编程竞赛提高自己编程水平。今天,我们来谈谈... 查看详情

图片压缩,用这个就够了(代码片段)

现在的智能手机分辨率都很高,拍的高清照片动辄5M甚至7M。上传到系统的图片太大了,导致页面加载缓慢。为此,让组里一小伙做一个压缩工具。发版后,发现图片虽然是压缩了,不过有个别图片严重失真。  然后,在... 查看详情

继续分享5个实用的vs调试技巧(代码片段)

继续分享5个实用的vs调试技巧原总结调试vs2019vs前言我在上一篇文章《5个非常实用的vs调试技巧》中分享了5个我认为非常值得了解的vs调试技巧,本周继续分享5个很基础但同样实用的调试技巧。1.条件断点作用简介:顾名思义,... 查看详情

c语言初阶笔记程序员必须要会的实用调试技巧(含库函数strcpy和strlen的模拟实现)!!(代码片段)

目录 为什么要学习调试?什么是bug?调试是什么,有多重要?调试的概念及重要性调试的步骤Debug和Release的介绍windows环境调试介绍1.调试环境的准备2.学会快捷键F5F9F10F11CTRL+F53.调试的时候查看程序当前信息查看临... 查看详情

做一个靠谱的工程师就够了

...口,I2C等接口。唯一比较麻烦的,就是有个射频的电路,这个一般是原厂会给参考电路设计的,详细的指标也不许要供应商去调试,只需要他们把电路设计好,板子回来之后做一下简单的测 查看详情