八,调试(新手)

八,调试

一,调试实战

1.例子1

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

以下代码有两个问题:1. 数组访问越界   2. 死循环
 以下代码再vs2013下会造成死循环,原因:
 栈内存:
         |CC  CC  CC  CC|
         arr[0]|01  00  00  00|\
         arr[1]|02  00  00  00| \
         arr[2]|03  00  00  00|  \
         arr[3]|04  00  00  00|   \
         arr[4]|05  00  00  00|    \
         arr[5]|06  00  00  00|    /  arr的空间
         arr[6]|07  00  00  00|   /
         arr[7]|08  00  00  00|  /
         arr[8]|09  00  00  00| /
         arr[9]|0A  00  00  00|/
               |CC  CC  CC  CC|
               |CC  CC  CC  CC|
               |00  00  00  00| i的空间
               |CC  CC  CC  CC|
for循环中,i的内容是从0,一直增加到12,而数组只有10个空间,因此会越界
每次访问arr数组i号位置时,都会将该位置内容设置为0,当访问到arr[12]时,
也会将该位置内容设置为0,而位置恰好为i的位置,即a[12]恰巧将i设置为0,因此造成死循环。

更进一步解释:i和arr是局部变量,是在内存中栈区存放的,而栈区的使用习惯是:先使用高地址处的空间,在使用低地址的空间。

又因为数据随着下标的增长,地址是从低到高变化的,所以有可能访问到i上,然后令i=0,无线循环。

2.例子2

#include <stdio.h>
int main()
{
    int i = 0;
    int sum = 0;
    int n = 0;
    int ret = 1;
    scanf("%d", &n);
    for (i = 0; i <= n; i++)
    {
        int j = 0;
        for (j = 1; j <= i; j++)
        {
            ret = ret * j;
        }
        sum += ret;
    }
    printf("%d\n", sum);
    return 0;
}

修改结果:

#include <stdio.h>
int main()
{
    int i = 0;
    int sum = 0;
    int n = 0;
    int ret = 0;
    scanf("%d", &n);
    for (i = 0; i <= n; i++)
    {
        int j = 1;
        if (j <= i)
        {
            for (j = 1, ret = 1; j <= i; j++)
            {
                ret = ret * j;
            }
        }
        sum += ret;
    }
    printf("%d\n", sum);
    return 0;
}

#include <stdio.h>

int main()
{
    int i, sum = 0, n, ret;
    scanf("%d", &n);

    for (i = 1, ret = 1; i <= n; i++)
    {
        ret *= i;
        sum += ret;
    }

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

修改过程:

image

问题很多:

image

发现问题一:多加了个(ret=1)

image

发现问题二:ret没有清0

解决篇:

解决问题尝试一:解决ret没有清0

image

解决问题尝试二:把多加的解决掉image

二,什么优秀的代码?怎么写出优秀的代码?

优秀的代码:

1.代码正常运行

2.bug少

3.效率高

4.可读性高

5.可维护性高

6.注释清晰

7.文档齐全

2.常用的coding技巧:

  1. 使用assert

  2. 使用const

  3. 养成良好的编码风格

  4. 添加必要的注释

  5. 避免代码陷阱

示范:

  1. 使用assert(断言)

    #include <stdio.h>
    #include<assert.h>
    char* my_strcpy(char* dest, const char* src)
    {
    //断言
    assert(dest != NULL);
    assert(src != NULL);
    while (*src != ‘\0’)
    {
    *dest = *src;
    dest++;
    src–;
    }
    *dest = *src;// \0的拷贝

    }
    int main()
    {
    char arr1[] = “hello world”;
    char arr2[20] = “xxxxxxxxxxxxxxxx”;
    char* p = NULL;
    printf(“%s\n”, my_strcpy(p, arr1));

    return 0;
    

    }

image

直接会报错

#include <stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
    //断言
    assert(dest != NULL);
    assert(src != NULL);
    while (*src != '\0')
    {
        *dest = *src;
        dest++;
        src++;
    }
    *dest = *src;//   \0的拷贝

}
int main()
{
    char arr1[] = "hello world";
    char arr2[20] = "xxxxxxxxxxxxxxxx";
    char* p = NULL;
    my_strcpy(arr2, arr1);
    printf("%s\n",arr2 );

    return 0;
}

#include <stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
    //断言
    assert(dest != NULL);
    assert(src != NULL);
    while (*dest = *src)
    {
        dest++;
        src++;
    }
}
int main()
{
    char arr1[] = "hello world";
    char arr2[20] = "xxxxxxxxxxxxxxxx";
    char* p = NULL;
    my_strcpy(arr2, arr1);
    printf("%s\n",arr2 );

    return 0;
}

#include <stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
    char* ret=dest;
    //断言
    assert(dest != NULL);
    assert(src != NULL);
    while(*dest++ = *src++)
      ;//空语句 
    return ret;
}
int main()
{
    char arr1[] = "hello world";
    char arr2[20] = "xxxxxxxxxxxxxxxx";
    char* p = NULL;
    printf("%s\n", my_strcpy(arr2, arr1));
    return 0;
}
  1. 使用const(保护作用)

const如果放在*左边那么说明维护的是指针,不能改变指针指向的内容,可以改变指针变量本身的内容

const如果放在*右边那么说明维护的是指针变量本身的内容,不能改变改变指针变量本身的内容,可以指针指向的内容

#include <stdio.h>
void test1()
{
	int n = 10;
	int m = 20;
	int* p = &n;
	*p = 20; //ok
	p = &m;  //ok
}
void test2()
{
	int n = 10;
	int m = 20;
	const int* p = &n;
	*p = 20; //错误
	p = &m;  //ok
}
void test3()
{
	int n = 10;
	int m = 20;
	int*const p = &n;
	*p = 20; //ok
	p = &m;  //错误
}
int main()
{
	test1();
	test2();
	test3();

	return 0;
}

3.编码常见的错误

  1. 编译型错误、

直接看错误信息,解决问题

  1. 链接型错误

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

一般是标识符不存在或者拼写错误

  1. 运行时错误

借助调试,逐步定位问题

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值