程序员必备技能之调试

这篇具有很好参考价值的文章主要介绍了程序员必备技能之调试。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

本期内容介绍

一、什么是Bug?

二、调试以及调试的重要性

2.1什么是调试?

2.2调试的基本步骤

​三、Debug和Release介绍

Debug和Release

四、windows环境下的调试介绍

4.1调试环境

4.2一些调试常用的快捷键

4.3调试时查看当前程序的信息

a、查看临时变量的值

b、查看程序的内存信息

c、查看程序的调用堆栈

d、查看程序的汇编信息

e、查看寄存器信息

五、一些调试实例

六、如何写出“好”代码?

6.1什么是好代码?

6.2如何写出好代码?

assert介绍

const介绍

七、常见的错误解析

7.1编译型错误

7.2链接型错误

7.3运行时错误


前言

我们平时在写代码的时候会出现各种错误,面对程序出现的错误我们之前好像没有介绍过如何高效、科学、系统地处理这种错误!您平时一般是如何说处理的呢?走读?猜?还是???无论哪种方式其实都是不是最高效且合理的!本期小编将介绍VS常用调试技巧!

本期内容介绍

什么是Bug?

调试及调试的重要性

Debug和Release介绍

windows环境调试介绍

一些调试实例

如何写出"好"代码?

常见错误解析

一、什么是Bug?

Bug的意思是:飞蛾或昆虫!在计算机中用Bug来代指一些未被发现的或隐藏的错误或缺陷!

下面是百度百科的介绍以及历史上第一个Bug的图片:

程序员必备技能之调试,C语言从入门到进阶,c语言

程序员必备技能之调试,C语言从入门到进阶,c语言

这是关于Bug的更详细的链接程序错误_百度百科 (baidu.com)感兴趣的可以看看!

二、调试以及调试的重要性

2.1什么是调试?

调试又称除错!是当程序或电子仪器出现了问题之后对程序或电子仪器进行科学排查、寻找问题以及解决问题的过程!

2.2调试的基本步骤

程序员必备技能之调试,C语言从入门到进阶,c语言

OK,我们来写个有问题程序来走一遍上面步骤:(求n的阶乘和)

int main()
{
	int n = 0;
	scanf("%d", &n);
	int sum = 0, ret = 1;//sum存储n的阶乘和 ret用于存储每一个的阶乘  
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= i; j++)
		{
			ret *= j;
		}
		sum += ret;
	}

	printf("sum  = %d",sum);
	return 0;
}

我们知道3!和为:1!+ 2! + 3! = 1 + 2*1 + 3* 2*1 = 9 我们来看结果:

程序员必备技能之调试,C语言从入门到进阶,c语言

怎么是15???这和我们的预期不一样,是不是就是出现了Bug了!我们就得想办法来解决这个问题!第一步:发现问题,结果和预期不一样,已经发现问题!第二步:定位问题:我们这里对变量sum 和 ret分别监视,一一比对每一次sum、ret的值是否与预期一样!第三步:确定错误原因:

程序员必备技能之调试,C语言从入门到进阶,c语言

这里确定了问题的原因,怎么解决呢?我们发现这里应该对每一个i的阶乘都要单独算,要就是说每一个ret都应该独立的,每一次的ret都应该是没有被用过的!那我们在每次计算每个i的时候对ret一开始先置 1即可!第四步:解决问题

int main()
{
	int n = 0;
	scanf("%d", &n);
	int sum = 0, ret = 1;//sum存储n的阶乘和 ret用于存储每一个的阶乘  
	for (int i = 1; i <= n; i++)
	{
		ret = 1;//防止后面的值重复叠加
		for (int j = 1; j <= i; j++)
		{
			ret *= j;
		}
		sum += ret;
	}

	printf("sum  = %d",sum);
	return 0;
}

OK,第五步:重新测试:

三、Debug和Release介绍

我们的VS编译器上会经常看到一个东西是Debug!

程序员必备技能之调试,C语言从入门到进阶,c语言

其实不止有Debug还有一个是Release!

程序员必备技能之调试,C语言从入门到进阶,c语言

他们是什么呢?下面我们就来介绍一下Debug和Release:

Debug和Release

Debug:

Debug被称为调试版本,它包含了调试信息,不做任何优化,用于程序员调试解决问题!

Release:

Release被称为发布版本,它往往是对程序进行了优化,是的代码在运行速度以及空间大小都是最优的!用于用户使用的!

无论是Debug还是Release只要编译就会有相应的文件包,(就和Java中的.class类似,一个类编译一次有一个.class文件):

只在Debug编译:

程序员必备技能之调试,C语言从入门到进阶,c语言

再在Release下编译:

程序员必备技能之调试,C语言从入门到进阶,c语言

由于Release是用户使用的所以不能用来调试,而Debug是对程序员的所以可以用来调试!

OK。我们来看一段代码看看在两个版本下的差异:

Debug:

int main()
{
	int i = 0; 
	int arr[10] = { 0 };
	for (i = 0; i <= 12; i++)
	{
		arr[i] = 0;
		printf("hehe\n");
	}
	return 0;
}

我们先不管结果为什么是这样!我们先来看看两者结果的差别!:

程序员必备技能之调试,C语言从入门到进阶,c语言

这可不是结束了,这就是典型的死循环!!!为什么死循环我们不管,待会分析!

再来看看Release版本下的结果:

程序员必备技能之调试,C语言从入门到进阶,c语言

这就很好的说明了release版本对程序的优化!!!具体如何优化的这个得问问微软的开发工程师~

四、windows环境下的调试介绍

4.1调试环境

本期所有调试都是在VS2019的Debug下进行的!!!

程序员必备技能之调试,C语言从入门到进阶,c语言

4.2一些调试常用的快捷键

程序员必备技能之调试,C语言从入门到进阶,c语言

这里应该最清楚的一个就是:ctrl+F5了我们执行代码就是这个,他其实是开始执行不调试!!!除此之外还有很多快捷键!我们下面介绍几个最常用的!

F5

启动调试,常用于直接跳到下一个断点处!(这个断点是逻辑断点,非物理断点)

F9

创建和取消断点,然后F5直接跳过去到当前断点位置,然后就可以一步一步调试观察是否和预期一样!

所以,F5和F9是一起配合使用的!

F10

逐过程,通常是用来处理一个过程例如一次函数调用或一条语句!

F11

逐语句,每一次只能执行一条语句,可以进到函数内部!

如果您在调试的时候,上面的键按一下不起作用的话,有可能是Fn打开了,关掉Fn即可或者是上面的键+Fn配合使用即可!!!

下面是知乎的一篇VS2019的调试技巧快捷键介绍:VS2019调试快捷键大全

4.3调试时查看当前程序的信息

a、查看临时变量的值

在开始调试之后如何查看临时变量的值!其实我们上面已经用到了,只不过刚刚没有介绍!

我们按下F10之后,启动调试后,点击调试,进去选择窗口找到监视,有四个窗口随便一个都可以!

程序员必备技能之调试,C语言从入门到进阶,c语言

OK,我们在来一个看一个代码顺便调试看一下临时变量!


void swap(int x, int y)
{
	int tmp = x; 
	x = y;
	y = tmp;
}

int main()
{
	int a = 3;
	int b = 5;
	printf("交换前:a = %d  b = %d\n", a, b);
	swap(a, b);
	printf("交换后:a = %d  b = %d\n", a, b);
	return 0;
}

这就是交换两个数的代码,我们先来看看结果!

程序员必备技能之调试,C语言从入门到进阶,c语言

似乎没有交换,其实原因我们都清楚--》形参是实参的一份临时拷贝,改变形参不改变实参!

这里我们假装不知道,我们此时程序的结果和我们的预期不符合出了问题!就需要调试,我们来练习一下刚刚学的!

程序员必备技能之调试,C语言从入门到进阶,c语言

这就是F9打的断点,我们分析程序是在swap函数出问题的,所以F9直接跳过没问题的.然后F5到当前断点来!

程序员必备技能之调试,C语言从入门到进阶,c语言

此时问题在函数里面,我们介绍过。F11是逐语句执行,我们可以用它进入函数内部,看看!

程序员必备技能之调试,C语言从入门到进阶,c语言

注意此时监视x = 3, y = 5, a = 3, b = 5, 我们待会观察a,b,x,y的变化情况!

程序员必备技能之调试,C语言从入门到进阶,c语言

这是调试结束的结果,此时x = 5, y = 3确实交换了,但a = 3, b = 5好像一点也没变!我们结束打印的是a 和 b:

程序员必备技能之调试,C语言从入门到进阶,c语言

结果还是a = 3, b = 5;所以没有交换成功!这里小编也就不废话了,这里改变了形参形参是实参的一份拷贝,两者的空间不同,改变形参实参不受影响!我们前面已经不止一遍的介绍过这东西了,这里就不在唠叨了!

b、查看程序的内存信息
int main()
{
	int a = 0x11223344;

	return 0;
}

这段代码的内存布局以及a的值在内存中是如何存的?我们一起来look一look:

还是先调试起来!!! 点调试--->窗口--->内存-->4个窗口随便一个!

程序员必备技能之调试,C语言从入门到进阶,c语言

程序员必备技能之调试,C语言从入门到进阶,c语言

这里输入&a就可以看到,a的内存布局以及a中的值在内存中的存储形式,我们前面介绍过倒着存是因为对当前平台是小端存储模式!

c、查看程序的调用堆栈

我们就用下面这个简单的代码演示一下:

void test2()
{
	printf("hahaha\n");
}

void test1()
{
	test2();
}

int main()
{
	test1();
	return 0;
}

这个代码就是打印一个haha,但它是如何调用的?我们就可以来看看调用堆栈!

先调试起来!!!再点击调试-->窗口-->调用堆栈

程序员必备技能之调试,C语言从入门到进阶,c语言

一开始还没有调用test1只有main函数的栈帧!

程序员必备技能之调试,C语言从入门到进阶,c语言

F11调用test1在main函数的上面开辟了test1的栈帧:

程序员必备技能之调试,C语言从入门到进阶,c语言

在调用test2就有在test1上面创建了test2的函数栈帧:

程序员必备技能之调试,C语言从入门到进阶,c语言

然后接下来打印完haha后就会把test2的函数栈帧销毁,我们在函数栈帧的那一期介绍过,在调用一个函数的时候会把当前语句的下一条语句提前存起来,等栈帧销毁的时候就直接执行下一条语句了!所以test2带哦万就销毁了,只剩test1和main函数的栈帧了!

程序员必备技能之调试,C语言从入门到进阶,c语言

然后会最后main函数的栈帧也会销毁!!!这里我又想起来了我在介绍函数栈帧的时候说过main函数是被其他函数调用的,但那时候操作不当在调用堆栈那里没有找到!今天小编找到了!

程序员必备技能之调试,C语言从入门到进阶,c语言

在VS上调用main函数的函数是用C++写的!当然这个具体实现得看编译器,各个编译器可能不一样!

d、查看程序的汇编信息

先调试起来!!!再点击调试-->窗口-->反汇编

程序员必备技能之调试,C语言从入门到进阶,c语言

int maxNum(int x, int y)
{
	return x > y ? x : y;
}

int main()
{

	int a = 3; 
	int b = 5;
	int ret = maxNum(a, b);
	printf("max = %d", ret);
	return 0;
}

程序员必备技能之调试,C语言从入门到进阶,c语言

红色的框是在建立函数栈帧!这个我们函数栈帧介绍过!下面蓝色的框是在创建变量!

程序员必备技能之调试,C语言从入门到进阶,c语言

这就是调用函数的指令!

程序员必备技能之调试,C语言从入门到进阶,c语言

这个就是maxNum的函数栈帧!!!!的创建以及销毁的反汇编!

e、查看寄存器信息

这个可能很多刚刚入门的或者还没入门的小伙伴都不知道!

寄存器(register)是cpu周围的暂时放数据的地方,由于在cpu周围所以访问速度很快但空间不大!而且在寄存器上创建的变量是没有地址的!!!!

OK,我们来段代码看看:

int main()
{
	int a = 3;
	register int b = 5;

	return 0;
}

b就是一个寄存器的变量!他是没有地址的!我们先对a取地址:

程序员必备技能之调试,C语言从入门到进阶,c语言

在对b 取地址:

程序员必备技能之调试,C语言从入门到进阶,c语言

在cpu周围不需要开辟内存直接可以使用!!!

五、一些调试实例

(一)、代码实现:1! + 2! + ...+n!

int main()
{
	int sum = 0;
	int ret = 1;
	int n = 0;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= i; j++)
		{
			ret *= j;
		}

		sum += ret;
	}

	printf("%d", sum);
	return 0;
}

这段代码我们其实一开始就介绍了,它的错误原因在于:每一次没有对ret初始化为1,导致后面的ret把前面的结果叠加的乘了上去!!!我们上面也调试了,这里就不在调试了!正确代码如下:

int main()
{
	int sum = 0;
	int ret = 1;
	int n = 0;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		ret = 1;
		for (int j = 1; j <= i; j++)
		{
			ret *= j;
		}

		sum += ret;
	}

	printf("%d", sum);
	return 0;
}

(二)、下列程序打印机次haha?

int main()
{
	int i = 0; 
	int arr[10] = { 0 };
	for (i = 0; i <= 12; i++)
	{
		arr[i] = 0;
		printf("haha\n");
	}
	return 0;
}

如果你以前没有见过这道题或了解过地层相关的知识的话,这道题你可能100%会回答错!你可能只会说这道题的问题不就是越界嘛!打印13个haha然后报错!但事实真的是这样吗?我们看结果:程序员必备技能之调试,C语言从入门到进阶,c语言

死循环了!!!问什么呢?我们先来找原因,其实如果之前看过函数栈帧的那一期的伙伴应该会反映过来,在VS上,创建的变量一个里一个差两行0hcccccccccc:

程序员必备技能之调试,C语言从入门到进阶,c语言

这里我们就不在用这种方式往下解释了,我们用调试:

程序员必备技能之调试,C语言从入门到进阶,c语言

果然他也是差了两行的ccccccccc,我们知道栈的使用规则是:先试用高地址,在使用低地址!而,数组的下标访问是先用低地址,后用高地址!

所以数组访问的地址路线如下:

程序员必备技能之调试,C语言从入门到进阶,c语言

会不会是在越界的时候把i改了呢?我们来监视看看:
刚刚创建好变量和数组:

程序员必备技能之调试,C语言从入门到进阶,c语言

i==9是,马上要越界了:

程序员必备技能之调试,C语言从入门到进阶,c语言

i == 12:

程序员必备技能之调试,C语言从入门到进阶,c语言

程序员必备技能之调试,C语言从入门到进阶,c语言

在i == 12,将arr[12] = 0;执行完后i也变成了0,我们猜想会不是越界的时候到i=12时将i的值改为了0?换句话说i的地址和arr[12]是一样的,他们是一块空间?我们此时只需要看看他两的地址即可:

程序员必备技能之调试,C语言从入门到进阶,c语言

果然一模一样!!!!我们上面的分析是正确的!!我在画个图来解释一下上面:

程序员必备技能之调试,C语言从入门到进阶,c语言

那找到了问题,确定了原因,就得解决问题:

int main()
{
	int arr[10] = { 0 };
	for (int i = 0; i <= 12; i++)
	{
		arr[i] = 0;
		printf("haha\n");
	}
	return 0;
}

这样写的话他i的创建在i的后面,前面的那块空间一单越界就会报错!

程序员必备技能之调试,C语言从入门到进阶,c语言

当然这种代码在实践中肯定是一般碰不到的!这个栗子仅仅是说明遇到问题了如何去解决!!!虽然在实践中遇不到但不一定在笔试面试中碰不到:这道题曾经就是一家叫Nice公司的笔试题:

程序员必备技能之调试,C语言从入门到进阶,c语言

这道提不就和刚刚这道题一样吗?只是换了数字而已!思路、问题、解决方法都是一样的!!!!

六、如何写出“好”代码?

6.1什么是好代码?

我们经常听说好代码,什么是好代码呢?我们认为具备以下特征的代码就是好代码!

1、能正常运行

2、Bug很少

3、效率高

4、可维护性高

5、注释清晰

6、可读性高

7、文档齐全

假设说你写了个代码,运行不了,或者即使运行起来了也全是Bug,你写的代码只有你自己你看的懂,不加注释。你可能说只有自己看得懂那不就公司裁不了我了吗?这样想就太天真了!当代码有几十万行时出了问题,你自己都控制不了的时候,,,你细品~。所以我们平时写代码要注重可读性以及注释!!!

6.2如何写出好代码?

这是一些写好代码的几个tips:

1、使用assert

2、使用const

3、编码风格规范

4、添加注释

这里提到了assert和const,我们以前经常用但没有介绍过这两个!下面我就先来介绍一下:

assert介绍

assert 中文意思就是断言的意思。顾名思义就是判断!他是一个宏!使用时要包含相应的头文件:#include <assert.h>

程序员必备技能之调试,C语言从入门到进阶,c语言

这是官网对他的介绍,人家明确说了这是一个!!!长得像函数的宏!作用是断言!如果它的判断的那个表达式判断失败就会调用:abort这个函数!并终止程序!这个宏所显示的消息与具体的实现库有关,一个编译器和一个编译器不一样!但他至少显示:断言失败的源文件名和对应的行数!如果你包含了头文件还是不能用就得添加上面我画出来的#definede 那个了!加上就OK了!!

这里还提到了一个函数:abort:

程序员必备技能之调试,C语言从入门到进阶,c语言

这个函数的作用是终止当前进程,进程是网络那部分的东西,这里就不多介绍了!这里就理解为终止当前程序(异常终止)!调用这个函数时这个函数会捕捉去一个信号,如果没有捕捉到,就会导致程序终止,并向平台返回一个错误码!程序被终止是不会破坏任何对象!!

OK!我们来写个代码用一下:

typedef struct Stu
{
	char name[20];
	int age;
}S;

void print(S* ps)
{
	assert(ps);
	printf("%d", ps->age);
}

void Modif(S* ps, int age)
{
	assert(ps);
	ps->age = age;
}
int main()
{
	S s = { "张三",20 };
	Modif(&s, 19);
	print(&s);
	return 0;
}

这就是assert的作用, 当然你可以按自己的需要判断值是否符合预期~!

const介绍

const这是一个关键字,我们前面开始介绍常量和变量的时候说过,被const 修饰的变量是常变量!具有常量属性但本质是个变量(只不过这个变量被初始化以后就不能在被修改了)!例如:

#define M 10//#define定义的常量

int main()
{
	int a = 3;//变量
	const int b = 5;//const修饰的常变量
	
	return 0;
}

因为b是被const修饰具有常量属性不能被改,所以这里对他的值进行修改就会报错:

程序员必备技能之调试,C语言从入门到进阶,c语言

而且也不可以用它来定义数组!我们知道定义数组时[ ]里面的是一个常量(变长数组除外),变量就不行,b是常变量所以他也不行!!!

程序员必备技能之调试,C语言从入门到进阶,c语言

当然我们今天不是为了回忆以前学的,而是在此基础上再进行拔高一层!比如const修饰指针的问题!先看如下代码:

void test1()
{
	int m = 3;
	int n = 5;
	int* p = &n;
	*p = 20;
	p = &m;
}

void test2()
{
	int m = 3;
	int n = 5;
	const int* p = &n;
	*p = 20;
	p = &m;
}

void test3()
{
	int m = 3;
	int n = 5;
	int* const p = &n;
	*p = 20;
	p = &m;
}

void test4()
{
	int m = 3;
	int n = 5;
	const int* const p = &n;
	*p = 20;
	p = &m;
}

int main()
{
	test1();
	test2();
	test3();
	test4();
	return 0;
}

上面的4个代码分是对指针p的 * 两边都不用const修饰,在*左边修饰右边不修饰,右边修饰左边不修饰,以及两边都修饰!具体会出什么结果过呢?我们一个一个看一看!

test1两边都不修饰:

程序员必备技能之调试,C语言从入门到进阶,c语言

考虑此时的 m 和 n值是多少?

程序员必备技能之调试,C语言从入门到进阶,c语言

这个不怎么难一看就知道但我想说的是!这里有一行很不起眼的代码你可能没有注意到!就是倒数第二行!p = &m;你可能会说这不就是一行很简单的赋值吗?这有啥可介绍的!你这么想就可使有点外行了!这可是指针啊!!!有了指针可以直接修改的!!!例如:

void test1()
{
	int m = 3;
	int n = 5;
	int* p = &n;
	*p = 20;
	p = &m;
	printf("m = %d  n = %d\n", m, n);
	*p = 200;
	printf("m = %d  n = %d\n", m, n);
}

看结果:

程序员必备技能之调试,C语言从入门到进阶,c语言

这里你还觉得他仅仅赋值那么简单吗?是不是感觉他很不安全呀!的确指针使用不当很危险!所以在使用指针前对他进行检查以及作相应的修饰限制,例如const,下面就来看看被const此时的各种情况吧!

const在*左边:

void test2()
{
	int m = 3;
	int n = 5;
	const int* p = &n;
	*p = 20;
	p = &m;
}

这个就是const修饰*左边的例子!如果被const修饰了左边,会和不修饰有什么区别呢?我们想爱你编译看看!

程序员必备技能之调试,C语言从入门到进阶,c语言

这貌似和const修饰一般的变量一样!不能被修改,这个在左边好像不能修改p指向那块空间的值!那我们猜测:如果在右边是不是不能改变p的值呢?我们来看看:

void test3()
{
	int m = 3;
	int n = 5;
	int* const p = &n;
	*p = 20;
	p = &m;
}

程序员必备技能之调试,C语言从入门到进阶,c语言

还真和我们猜的一样!再回到上面的栗子test2:

void test2()
{
	int m = 3;
	int n = 5;
	const int* p = &n;
	//*p = 20;
	p = &m;
	p = NULL;
}

既然不让修改p指向的值的话,那我改变p的值,的确可以!

程序员必备技能之调试,C语言从入门到进阶,c语言

和这个类比一下,在右边我不能改 p的值,那我可以改p指向的那块空间的值吧!验证一下:

程序员必备技能之调试,C语言从入门到进阶,c语言

果然!那我们可以再猜测一下是不是在两边修饰就是既不能修改p的值也不能修改p只向空间的值呢?试一试:

程序员必备技能之调试,C语言从入门到进阶,c语言

果然!这样好像更安全了~的确是!我们现在就可以进行总结一下!

const 两边都不修饰

很不安全!!!只要拿到指针既可以修改指针也可以修改指针指向的空间的值!

const 修饰*左边

不能对指针指向的那块空间的值进行修改!但可以对指针的修改!

const 修饰*右边

不能修改指针的值,但可以修改指针指向空间的值!

const 修饰两边

既不能修改指针的值,也不能修改指针指向空间的值!

OK,这三种修饰看具体情况使用!!!!!我们刚刚上面的aeesrt的那个代码是不是可以再来用优化一下呢?

typedef struct Stu
{
	char name[20];
	int age;
}S;

void print(const S* const ps)
{
	assert(ps);
	printf("%d", ps->age);
}

void Modif(S* const ps, int age)
{
	assert(ps);
	assert(age);

	ps->age = age;
}
int main()
{
	S s = { "张三",20 };
	Modif(&s, 19);
	print(&s);
	return 0;
}

程序员必备技能之调试,C语言从入门到进阶,c语言

print函数只是打印信息不需要改变ps的值以及ps指向空间的值!下面的修改函数是需要修改ps指向空间的值但不需要改变自身的值~,加上assert和const的代码是不是更加健壮了!以后能用就多用!!!另外多加注释!!!OK,下面我们就来完整的写一个好代码!模拟实现strcpy!这个函数不必多介绍了吧,我们已经前面模拟实现了两遍了!它的作用就是拷贝字符串!~函数原型如下:

程序员必备技能之调试,C语言从入门到进阶,c语言

两个参数,destination是目的地也即是要拷贝到的空间!另一个是,cosnt修饰的source是源头,也就是要拷贝的数据!因为他只要求拷贝不让修改,所以const修饰左边!我们下面来实现一个:

char* MyStrcpy(char* dest, const char* src)
{
	//检查空指针
	assert(dest);
	assert(src);

	//拷贝
	char* ret = dest;
	while (*dest++ = *src++)
		;

	return ret;
}

int main()
{
	char dest[20] = { 0 };
	char* src = "hello world!";
	strcpy(dest, src);//库函数
	printf("%s\n", dest);
	printf("-----------------------\n");
	MyStrcpy(dest, src);//自己函数
	printf("%s\n", dest);
	return 0;
}

看结果:

程序员必备技能之调试,C语言从入门到进阶,c语言

OK!模拟完成!

七、常见错误解析

7.1编译型错误

一般可以直接看到错误信息,凭借经验就可以解决!一半多为语法错误~

例如:

int main()
{
	int a = 3
	return 0;
}

这里是少个封号,导致语法错误!看编译错误信息:

程序员必备技能之调试,C语言从入门到进阶,c语言

这种问题一般会很简单,看看错误信息就可以解决!

7.2链接型错误

这种错误一般是由标识符错误火不存在导致的!看错误信息也很容易解决!

int Add(int a, int b)
{
	return a + b;
}

int main()
{
	int a = 3;
	int b = 5;
	int ret = add(a, b);
	printf("%d", ret);
	return 0;
}

这里add和Add不是一个东西就会表连接时错误!

程序员必备技能之调试,C语言从入门到进阶,c语言

这种找到改回来就好了!

7.3运行时错误

这是最麻烦的一种,语法没有问题可是结果就是不符合预期,得一步一步调试~

调试也是程序员的内功,非一日之功!~得多练习~,!

OK,好兄弟本期分享就到这里,我们下期再见~!文章来源地址https://www.toymoban.com/news/detail-692372.html

到了这里,关于程序员必备技能之调试的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 程序员技能与成长:如何学习新的编程语言和代码规范与单元测试

    一名软件工程师的最大挑战就是使自己的技术栈跟得上技术的发展,而在这个技术飞速发展的时代,保证自己不被淘汰的唯一方法就是不断学习。 那么,程序员需要掌握多门编程语言吗?很多初学者都被这个问题所困扰。Google研究总监 Peter Norvig曾就这个问题给出自己的观点

    2024年04月10日
    浏览(46)
  • 程序员必备APP

      我在IT界摸爬滚打的也挺长时间了,我看见了挺多的人都想要进入这个行业,之前就有一个小姑娘来问我,如果想要成为程序员的话,需要使用什么软件,学会什么技能,今天我就就着这个话题 给大家分享一下,程序员应该知道的一些应用 ,给各位一个小小的参考。 一款

    2023年04月08日
    浏览(64)
  • 程序员必备算法(详细)

    算法的重要性和应用场景: 算法是解决问题的步骤和规则,它们在计算机科学和软件开发中至关重要。 算法可以提高程序的执行效率、降低资源消耗,并改善用户体验。 算法应用于各个领域,如数据处理、图形图像处理、网络和安全、人工智能等。 程序员需要掌握算法的原

    2024年02月15日
    浏览(83)
  • Linux必备基础命令,JAVA程序员必备

    目录 一、了解基本的左侧栏什么意思​编辑 二、ls,ll(list,查找目录内容) 三、cd(change directory,切换目录) 小技巧,我们在查找东西的时候,可以使用tab进行智能补全。 四、touch(建立文件) echo(打印到控制台) 五、vim(对文件进行更细粒度的编辑) 六、mkdir(创建目录

    2024年02月05日
    浏览(93)
  • 程序员必备的面试技巧

    “程序员必备的面试技巧,就像是编写一段完美的代码一样重要。在面试战场上,我们需要像忍者一样灵活,像侦探一样聪明,还要像无敌铁金刚一样坚定。只有掌握了这些技巧,我们才能在面试的舞台上闪耀光芒,成为那个令HR们心动的程序猿!” 提醒:在发布作品前,请

    2024年01月21日
    浏览(54)
  • 程序员最重要的技能是啥?

    若论工作中最重要的能力,莫过于甩锅了。我这么说并不是教人推卸责任,而是团队协作中因果都是交织的,没有孤立的过错。所以实际很难切割清楚,出现问题,完全就看谁能占据说理的上风,把责任推给别人。毕竟背锅的人有很大概率要丢工作的。所以,千万要小心。吹

    2024年02月02日
    浏览(49)
  • C++程序员必备的面试技巧

      “程序员必备的面试技巧,就像是编写一段完美的代码一样重要。在面试战场上,我们需要像忍者一样灵活,像侦探一样聪明,还要像无敌铁金刚一样坚定。只有掌握了这些技巧,我们才能在面试的舞台上闪耀光芒,成为那个令HR们心动的程序猿!” 在准备C++程序员面试时

    2024年02月01日
    浏览(52)
  • 程序员必备的10张流程图

    随着互联网的发展,现在有越来越多的人想成为程序员。 如果你想成为程序员你可以先问自己这几个问题? •你是一个逻辑和抽象思维能力比较强的人吗? •你是否愿意不断地去学习那些新的东西,并且在大多数时间内你都需要去自学。 •当你遇到一些问题和困难的时候,

    2024年02月07日
    浏览(55)
  • 程序员必备之——代码托管工具 git

    目录 一、git的安装及本地配置 1.1、git介绍 1.2、git本地安装及配置 1.3、git远程仓库 二、git的命令及使用 2.1、基础命令 三、git的分支 3.1、常用命令 3.2、执行效果图 3.3、合并时有冲突该怎么办? 3.4、解决冲突 3.5、git分支图解 四、连接远程仓库 4.1、在gitee新建远程仓库 4.2、

    2024年02月08日
    浏览(53)
  • 【必备】计算机行业、程序员必备的工具和软件 拒绝标题党

    博主并不是广告推销 只是分享自己接触的好用的软件和工具,所以一切从简 不会用长篇大论去介绍优点。 博主自己的笔记本是在用来办公的,所以不会去下载一切乱七八糟的东西,这些软件或工具 要么有自己的官方下载安装渠道 要么是开源的。 火绒 一个轻量的杀毒软件,

    2023年04月24日
    浏览(73)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包