❤欢迎各位大佬访问:折枝寄北-CSDN博客折枝寄北擅长C语言初阶,等方面的知识,折枝寄北关注python,c++,java,qt,c语言领域.https://blog.csdn.net/2303_80170533?type=blog
❤文章所属专栏https://blog.csdn.net/2303_80170533/category_12794764.html?spm=1001.2014.3001.5482
前言:
在C语言编程的初阶阶段,代码调试是一项至关重要的技能。无论是初学者还是经验丰富的程序员,都会遇到代码无法按预期运行的情况。这时,掌握一些有效的调试技巧能够显著提高问题解决效率,使编程过程更加顺畅。
代码调试技巧涵盖了从基本的语法错误检查到复杂的逻辑问题排查。这包括使用调试工具(如GDB)、添加调试信息(如打印语句)、设置断点、单步执行代码、检查变量值以及内存分配等。通过这些方法,开发者可以逐步缩小问题范围,定位并修复代码中的错误。
掌握良好的代码编写习惯,如模块化设计、清晰的变量命名和合理的注释,也能在调试过程中起到事半功倍的效果。这些习惯不仅有助于自己理解代码,还能让他人在需要时快速上手并协助调试。
1.什么是bug?
bug的来由(文心一言提供的解答)
-
昆虫起源:在计算机科学中,“bug”一词最初是指实际上的昆虫。在计算机发展的早期阶段,如电子管计算机和晶体管计算机时期,计算机的物理结构相对庞大且复杂,机器内部布满了错综复杂的电路和线路。这些环境很容易吸引各种昆虫,尤其是像蟑螂、蜘蛛等小昆虫。这些小昆虫有时会爬到电路板上,造成短路或断路,从而导致计算机出现故障。因此,工程师们开始用“bug”来形象地描述这种由昆虫引起的计算机故障。
-
历史记录:据说,在1945年9月9日,美国哈佛大学的Grace Hopper(格蕾丝·霍珀)博士在调试Mark II计算机时,发现了一只死蛾子(moth)卡在继电器触点之间,从而导致了计算机故障。她将这个蛾子用胶带粘在日志本上,并标注了“First actual case of bug being found”(第一个发现的实际bug案例)。这一事件被广泛认为是“bug”一词在计算机领域中的起源。
2.调试的作用
调试(英语:Debugging / Debug),又称除错,是发现和减少计算机程序或电子仪器设备中程序 错误的一个过程。
调试的步骤
发现程序错误的存在
以隔离、消除等方式对错误进行定位
确定错误产生的原因
提出纠正错误的解决办法
对程序错误予以改正,重新测试
3.debug和release的介绍
Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。 Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优 的,以便用户很好地使用。
int main()
{
int n = 0;
int a = 0;
scanf("%d %d", &a, &n);//2 5
//计算
int sum = 0;
int i = 0;
int k = 0;
for (i = 0; i < n; i++)
{
k = k * 10 + a;
sum += k;
}
//打印
printf("%d\n", sum);
return 0;
}
上述代码在Debug环境的结果展示:
上述代码在Release环境的结果展示:
所以我们说调试就是在Debug版本的环境中,找代码中潜伏的问题的一个过程。
4.windows环境调试介绍
4.1 调试环境的准备
调试代码,要选择在Debug环境下进行
4.2 学会使用快捷键
按f10就进入了调试,在上方图片中我们可以看见如何进行调试查看相应的变量及运行步骤
最常使用的几个快捷键:
F5 启动调试,经常用来直接跳到下一个断点处。
F9 创建断点和取消断点 断点的重要作用,可以在程序的任意位置设置断点。 这样就可以使得程序在想要的位置随意停止执行,继而一步步执行下去。
F10 逐过程,通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句。
F11 逐语句,就是每次都执行一条语句,但是这个快捷键可以使我们的执行逻辑进入函数内部(这是最 长用的)。
CTRL + F5 开始执行不调试,如果你想让程序直接运行起来而不调试就可以直接使用。
CTRL+F可以进行查询文件中的变量名等
4.3 调试的时候查看程序当前信息
查看临时变量的值 在调试开始之后,用于观察变量的值。
5.如何写出好的代码(易于调试)
1. 代码运行正常 2. bug很少 3. 效率高 4. 可读性高 5. 可维护性高 6. 注释清晰 7. 文档齐全
1. 使用assert()//断言
2. 尽量使用const
3. 养成良好的编码风格
4. 添加必要的注释
5. 避免编码的陷阱。
//实现库函数strlen--求字符串长度
unsigned int my_strlen(const char * str)
{
int count = 0;
assert(str != NULL);
while (*str++ != '\0')
{
count++;
}
return count;
}
int main()
{
char arr[] = "abcdef";
printf("%d\n", my_strlen(arr));
return 0;
}
注意:
1. 分析参数的设计(命名,类型),返回值类型的设计
2.野指针,空指针危害
3. assert的使用,assert的作用
4. 参数部分 const 的使用
void my_strcpy(char* dest, char* src)
{
//if (src == NULL || dest == NULL)//防止空指针
//{
// return;
//}
//断言
//assert中可以放一个表达式,表达式的结果为假就会报错
//如果为真,什么事都不会发生
//assert在release版本中优化了
/*assert(src != NULL);
assert(dest!= NULL);*/
assert(src && dest);
while (*dest++ = *src++)// \0的ASCII码值为0,while循环判断为假,停止
{
;
}
}
//const修改指针变量的时候
//1.const放在*的左边,修饰的是指针指向的内容,表示指针指向的内容,不能通过指针改变了
//const int* p=#
//
//2.const放在*的右边,const修饰的是指针变量本身,
// 表示指针变量本身的内容不能改变,但是指针指向的内容不能改变
//int* const p=#
//int main()
//{
// /*const int num = 10;
// const int* p = #
// *p = 20;*/
// //printf("%d\n", num);
//
// return 0;
//}
6.编程常见的错误
1 编译型错误 直接看错误提示信息(双击),解决问题。或者凭借经验就可以搞定。相对来说简单。
2 链接型错误 看错误提示信息,主要在代码中找到错误信息中的标识符,然后定位问题所在。一般是标识符名不 存在或者拼写错误。
3 运行时错误 借助调试,逐步定位问题。最难搞。