一、什么是bug
第一次被发现的导致计算机错误的飞蛾,也是第一个计算机程序错误。
指代计算机上存在的漏洞 软件缺陷
二、调试是什么?有多重要?
所有发生的事情都一定有迹可循,如果问心无愧,就不需要掩盖也就没有迹象了,如果问心有 愧,就必然需要掩盖,那就一定会有迹象,迹象越多就越容易顺藤而上,这就是推理的途径。顺 着这条途径顺流而下就是犯罪,逆流而上,就是真相。
1、调试
调试
(英语:Debugging / Debug),又称除错,是发现和减少计算机程序或电子仪器设备中程 序错误的一个过程。
2、调试的基本步骤
- 发现程序错误的存在
- 程序员
- 测试人员 --> 发布
- 用户
- 以隔离、消除等方式对错误进行定位
- 确定错误产生的原因
- 提出纠正错误的解决方法
- 对程序错误予以改正,重新测试
三、Debug和Release
Debug - 调试版本 - 可以调试
Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。
Release - 发布版本 - 用户使用的,不能调试
Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优 的,以便用户很好地使用。
四、windows环境调试介绍
1、调试环境的准备
在环境中选择 debug 选项,才能使代码正常调试
2、学会快捷键
Ctrl+U 改大小 Ctrl+Shift+U
VS改大小写的快捷键
改成小写:Ctrl+U
改成大写:Ctrl+Shift+U
记得要选中要修改的一段英文。
F5 启动调试
启动调试,经常用来直接跳到断点处,
在执行流程中的断点,想要跳到下一个断点,取消当前循环的断点,F5跳到下一个循环的断点处。
F9 启用/关闭断点
创建断点和取消断点 (F5要和F9配合使用 )
断点的重要作用,可以在程序的任意位置设置断点。
这样就可以使得程序在 想要的位置随意停止执行,继而一步步执行下去。
点住断点 右击 条件断点 可以设置条件 不用一一循环
F10 逐过程
逐过程,通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句。
F11 逐语句
逐语句,就是每次都执行一条语句,但是这个快捷键可以使我们的执行逻辑进入函数内部(这是 最常用的)。
CTRL + F5 开始执行(不调试)
开始执行不调试,如果你想让程序直接运行起来而不调试就可以直接使用。
#include <stdio.h>
void test() //F11 进入函数内部
{
printf("hehe\n");
}
int main()
{
int arr[10] = {0};
int i = 0;
test(); //F11
for(i=0; i<10; i++)
{
scanf("%d", arr[i]);
}
for(i=0; i<10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
其他快捷键
Ctrl+F5:查找
Ctrl+H: 替换
Ctrl G:转到行
Ctrl+K C: 注释选定内容
Ctrl+K U: 取消选定注释内容
END选择至行尾
HOME选择至行开始处
3、调试的时候查看程序当前信息

3.1、查看临时变量的值
监视 delete删除
#include <stdio.h>
void test() //F11 进入函数内部
{
printf("hehe\n");
}
int main()
{
int arr[10] = {0};
int i = 0;
test(); //F11
for(i=0; i<10; i++)
{
scanf("%d", arr[i]);
}
for(i=0; i<10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
3.2、查看内存信息
3.3、查看调用堆栈
通过调用堆栈,可以清晰的反应函数的调用关系以及当前调用所处的位置。
#include <stdio.h>
void test2()
{
printf("test2\n");
}
void test1()
{
test2();
}
void test()
{
test1();
}
int main()
{
test();
return 0;
}

3.4、查看汇编信息
在调试开始之后,有两种方式转到汇编:
(1)第一种方式:右击鼠标,选择【转到反汇编】:
(2)第二种方式:调试 窗口 反汇编
3.4、查看寄存器信息
可以查看当前运行环境的寄存器的使用信息。
五、一些调试的实例
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;
}
这时候我们如果3,期待输出9,但实际输出的是15。
通过调试发现是ret没有初始化
初始化后:
int main()
{
int i = 0;
int sum = 0;//保存最终结果
int n = 0;
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
int ret = 1;//保存n的阶乘
int j = 0;
for (j = 1; j <= i; j++)
{
ret *= j;
}
sum += ret;
}
printf("%d\n", sum);
return 0;
}
2、越界访问
#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;
}
越界访问,有可能访问到i,死循环
i<=10时报错,因为一直在循环,没有时间报错



NICE 笔试题

3、Debug版本对比
int main()
{
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%p\n", &i);
printf("%p\n", &arr[0]);
printf("%p\n", &arr[9]);
return 0;
}
Debug
此时,i 的地址比数组最后一个元素还大,说明如果越界访问,有可能虎访问到i,导致错误。
–
Release版本
没有报错,打印了 个hehe,没有死循环,
Release数组的地址比 i 的地址大,
因为进行了优化,把i放在arr之后,
《C陷阱与缺陷》

六、编程常见的错误
常见的错误分类:
1、编译型错误
直接看错误提示信息(双击),解决问题。或者凭借经验就可以搞定。相对来说简单。
2、链接型错误
看错误提示信息,主要在代码中找到错误信息中的标识符,然后定位问题所在。一般是标识符名 不存在或者拼写错误。
3、运行时错误
借助调试,逐步定位问题。最难搞。


–
七、如何写出好(易于调试)的代码。
优秀的代码:
- 代码运行正常
- bug很少
- 效率高
- 可读性高
- 可维护性高
- 注释清晰
- 文档齐全
常见的coding技巧:
- 使用assert
- 尽量使用const
- 养成良好的编码风格
- 添加必要的注释
- 避免编码的陷阱
一、模拟实现库函数:strcpy
Null - \0
null - \0
NULL - 空指针
1、strcpy
#include <stdio.h>
#include <string.h>
int main()
{
//strcpy - string copy - 字符串拷贝
char arr1[] = "abcdef";
char arr2[10] = { 0 };
strcpy(arr2, arr1); //arr2目标数组
printf("%s\n", arr2);
return 0;
}
2、my_strcpy
1
//dest 是指向目标空间的
//src 是指向原字符串的
void my_strcpy(char* dest, char* src)//目标 源头
{
while (*src != '\0') // \0=0 当指向\0时停止
{
*dest = *src;
dest++;
src++;
}
*dest = *src; //strcpy把\0一起拷贝 出循环指向的是\0 拷贝\0
}
int main()
{
//strcpy - string copy - 字符串拷贝
char arr1[] = "abcdef";
char arr2[10] = { 0 };
my_strcpy(arr2, arr1); //arr2目标数组
printf("%s\n", arr2);
return 0;
}
2优化 后置++
void my_strcpy(char* dest, char* src)
{
while (*src != '\0')
{
*dest++ = *src++; //后置++
}
*dest = *src; // \0
}
3优化
void my_strcpy(char* dest, char* src)
{
//1. 拷贝字符
//2. 遇到\0 循环停止
while (*dest++ = *src++)
{
;
}
}
4优化 判断空指针
#include <assert.h>
void my_strcpy(char* dest, char* src)
{
/*if (src == NULL || dest == NULL)
{
return;
}*/
assert(src != NULL); //断言 - release版本可以优化掉
assert(dest != NULL);
//assert发现问题会告诉我们
/*assert(src);
assert(dest);
assert(src && dest);*/
while (*dest++ = *src++)
{
;
}
}
const
用法
int main()
{
const int num = 10; //num是常变量
//num = 20; //err
int* p = #
*p = 20; //可以修改
printf("%d\n", num);
}
const修饰指针 *左右
int main()
{
const int num = 10;
//const修饰指针
//const 放在*的左边
//修饰的是指针指向的内容(*p),指针指向的内容,不能通过指针来改变了
//但是指针变量本身(p)是可以改变的
int n = 100;
const int* p = # //写法相同int const * p = #
*p = 20;
p = &n;
printf("%d\n", num); //修饰的是p 此时p不能存放n的地址
//const 放在*的右边
//修饰的是指针变量本身(p),指针变量本身(p)不能修改了
//指针指向的内容(*p)可以修改,
int n = 100;
int * const p = # //修饰的是*p 指针所指向的对象
*p = 20;
p = &n;
printf("%d\n", num);
}
5优化 const
健壮性/鲁棒性 - 抗风险
#include <assert.h>
void my_strcpy(char* dest, const char* src) //修饰*src 保护src不被修改
{
assert(src != NULL);
assert(dest != NULL);
while (*src++ = *dest++) //如果写反
{
;
}
}
6优化 返回类型
#include <assert.h>
char* my_strcpy(char* dest, const char* src)
{
assert(src != NULL);
assert(dest != NULL);
char* ret = dest; //先存起来 下面已经指向src对应得\0的位置 不是起始位置
while (*dest++ = *src++)
{
;
}
return ret; //返回目标起始位置
}
int main()
{
char arr1[] = "abcdef";
char arr2[10] = "xxxxxxxxxx";
char* ret = my_strcpy(arr2, arr1); //arr2目标数组
printf("%s\n", ret);
//只打印abcdef 没有打印后面的xxxx是因为字符串的结束标志是\0
return 0;
}
数组的错误情况
int main()
{
//1
char arr1[] = "abcdef"; //[a b c d e f \0]
char arr2[] = "xxxxxxxxx";
//2 - 原字符串中一定要有\0
char arr1[] = { 'a', 'b', 'c' };
char arr2[10] = "xxxxxxxxx";
//3 - 目标空间一定要足够大
char arr1[] = "abcdef";
char arr2[3] = { 0 };
//4 - 目标空间必须可修改
char arr1[] = "abcdef";
const char* arr2 = "xxxxxxxxxxxxxxx"; //指针指向的内容 不希望被修改时 加const 更严谨安全
//arr2是指针 指向常量字符串,常量字符串是放在常量区,是不能修改的
//不能拷贝,因为目标空间arr2不能被修改
char* ret = my_strcpy(arr2, arr1);
printf("%s\n", ret);
return 0;
}
打印字符串 解引用打印一个字符
int main()
{
char arr[] = "abcdef";
const char* str = "kel";
//打印字符串
printf("%s\n", arr);
printf("%s\n", str);
//字符指针 解引用 只能访问一个字符
//arr访问的是a 打印的是字符%c
printf("%c\n", *arr); //a
printf("%c\n", *str); //k
return 0;
}
常量字符串首字符地址存放在指针
int main()
{
const char* str = "abcdef";
//常量字符串abcdef在内存的常量区里
//把常量字符串首字符a的地址存放在str中
printf("%s\n", str); //abcdef
printf("%c\n", *str); //a
return 0;
}
二、模拟实现strlen函数
#include <assert.h>
//size_t - unsigned int 扩大范围
unsigned int my_strlen(const char* str)
{
assert(str != NULL);
int count = 0;
while (*str)
{
count++;
str++;
}
return count;
}
int main()
{
char arr[] = "abcdef";
int ret = my_strlen(arr);
printf("%d", ret);
return 0;
}
strlen返回类型是无符号数
int main()
{
//3-6 = -3
//10000000000000000000000000000011 - 原
//11111111111111111111111111111100 - 反
//11111111111111111111111111111101 - -3补码
//在内存中被解析为无符号数 全都是有效位
//补码即原码 是一个很大的正数
if (strlen("abc") - strlen("abcdef") > 0)
{
printf("hehe\n"); //hehe
}
else
{
printf("haha\n");
}
return 0;
}
八、练习
1、前置 / 后置++
#include <stdio.h>
int main()
{
int a, b, c;
a = 5;
c = ++a;
b = ++c, c++, ++a, a++;
b += a++ + c;
printf("a = %d b = %d c = %d\n:", a, b, c);
//a:9, b:23, c:8
return 0;
}
2、统计二进制中1的个数
写一个函数返回参数二进制中 1 的个数。
比如: 15 0000 1111 4 个 1
2.1、用&1和>>方法
size_t count_bit_one(int n)
{
int i = 0;
int count = 0;
for (i = 0; i < 32; i++) //i==31时 最高位来到最低位
{
//最低位和1按位与 如果是1按位与后结果就是1
//00000000000000000000000000001111 - 15
//00000000000000000000000000000001 - 1
//00000000000000000000000000000001 - &1 最低位是1 结果就是1
//按位与后>>
if (((n >> i) & 1) == 1) //当i=0时 没有右移
{
count++;
}
}
return count;
}
int main()
{
int num = 0;
scanf("%d", &num);
int ret = count_bit_one(num);
printf("%d\n", ret);
return 0;
}
2.2、用%2方法
十进制%10 /10可以得到每一位
123%10=3
12/10=12
12%10=2
//负数算不了 用无符号数
size_t count_bit_one(unsigned int n) //把负数当成无符号数求
{
int count = 0;
while (n)
{
if (n % 2 == 1)
{
count++;
}
n /= 2;
}
return count;
}
int main()
{
int num = 0;
scanf("%d", &num);
int ret = count_bit_one(num);
printf("%d\n", ret);
return 0;
}
2.3、用n-1&
size_t count_bit_one(int n)
{
int count = 0;
while (n)
{
n = n & (n - 1);
count++;
}
return count;
}
int main()
{
int num = 0;
scanf("%d", &num);
int ret = count_bit_one(num);
printf("%d\n", ret);
return 0;
}
3、写一个代码,判断一个数是不是2的次方数
2 – 0010
4 – 0100
8 – 1000
16 – 10000
int main()
{
int n = 0;
scanf("%d", &n);
if ((n & (n - 1)) == 0)
{
printf("YES\n");
}
else
{
printf("N0\n");
}
return 0;
}

IO型 - 自己写输入,输出
接口型 - 只要完成指定接口就可以了
4、统计二进制中1的个数
题目内容:
写一个函数返回参数二进制中 1 的个数。
比如: 15 0000 1111 4 个 1
//C++
class Solution {
public:
int NumberOf1(int n) {
int count = 0;
while (n)
{
n = n & (n - 1);
count++;
}
return count;
}
};
5、求两个数二进制中不同位的个数
题目内容:
编程实现:两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?
输入例子 :
1999 2299
输出例子 : 7
循环
int main()
{
int n1 = 0;
int n2 = 0;
scanf("%d %d", &n1, &n2);
int count = 0;
int i = 0;
for (i = 0; i < 32; i++)
{
if (((n1 >> i) & 1) != ((n2 >> i) & 1))
{
count++;
}
}
printf("%d\n", count);
return 0;
}
函数
int count_diff_bit(int n1, int n2)
{
int count = 0;
int i = 0;
for (i = 0; i < 32; i++)
{
if (((n1 >> i) & 1) != ((n2 >> i) & 1))
{
count++;
}
}
return count;
}
int main()
{
int n1 = 0;
int n2 = 0;
scanf("%d %d", &n1, &n2);
int count = count_diff_bit(n1, n2);
printf("%d\n", count);
return 0;
}
对应的二进制位^ 同为0异为1
int NumberOf1(int n) //求一个数二进制有多少个1
{
int count = 0;
while (n)
{
n = n & (n - 1);
count++;
}
return count;
}
int count_diff_bit(int n1, int n2)
{
int count = 0;
int t = n1 ^ n2;
count = NumberOf1(t);
return count;
}
int main()
{
int n1 = 0;
int n2 = 0;
scanf("%d %d", &n1, &n2);
int count = count_diff_bit(n1, n2);
printf("%d\n", count);
return 0;
}
6、打印整数二进制的奇数位和偶数位
题目内容:
获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列
/偶数位 1 3 5 7。。。31
奇数位 0 2 4 6 。。。30
倒着打印 所以从后开循环
int main()
{
int num = 0;
scanf("%d", &num);
int i = 0;
printf("偶数位:");
for (i = 31; i >= 1; i -= 2)
{
printf("%d ", (num >> i) & 1);
}
printf("\n奇数位:");
for (i = 30; i >= 0; i -= 2)
{
printf("%d ", (num >> i) & 1);
}
printf("\n");
return 0;
}
7、判断是元音还是辅音
多组输入,每行输入一个字母。
输出描述:
针对每组输入,输出为一行,如果输入字母是元音(包括大小写),
输出“Vowel”,如果输入字母是非元音,输出“Consonant”。
循环判断
int main()
{
int ch = 0;
//循环判断部分其实是在读取字符
while ((ch = getchar()) != EOF)
{
//判断是否为元音字母
if (ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U' || ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
{
printf("Vowel\n");
}
else
{
printf("Consonant\n");
}
getchar(); //清理 \n
}
return 0;
}
字符数组判断
int main()
{
int ch = 0;
char vowel[] = "aeiouAEIOU";
while ((ch = getchar()) != EOF)
{
int i = 0;
int flag = 0;
for (i = 0; i < 10; i++)
{
if (ch == vowel[i])
{
flag = 1;
break;
}
}
if (flag == 1)
{
printf("Vowel\n");
}
else
{
printf("Consonant\n");
}
getchar(); //清理 \n
}
return 0;
}
//3.改大小写
//4.strstr
–
8、矩阵相等判断
第一行包含两个整数n和m,表示两个矩阵包含n行m列,用空格分隔。
从2到n + 1行,每行输入m个整数(范围 - 231~231 - 1),用空格分隔,共输入n * m个数,表示第一个矩阵中的元素。
从n + 2行到2n + 1,每行输入m个整数(范围 - 231~231 - 1),用空格分隔,共输入n * m个数,表示第二个矩阵中的元素。
1 < n, m < 10
输出描述:
一行,如果两个矩阵相等输出"Yes"并换行,否则输出"No"并换行。
int main()
{
int arr1[10][10] = { 0 };
int arr2[10][10] = { 0 };
int n = 0;
int m = 0;
scanf("%d %d", &n, &m);
int i = 0;
int j = 0;
//输入了矩阵1
//n行
for (i = 0; i < n; i++)
{
//m列
for (j = 0; j < m; j++)
{
scanf("%d", &arr1[i][j]);
}
}
//输入了矩阵2
for (i = 0; i < n; i++)
{
//m列
for (j = 0; j < m; j++)
{
scanf("%d", &arr2[i][j]);
}
}
//判断
int flag = 1; //默认相同
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
if (arr1[i][j] != arr2[i][j])
{
flag = 0;
break;
}
}
}
if (flag == 1)
{
printf("Yes\n");
}
else
{
printf("No\n");
}
return 0;
}
优化 读一个判断一个
int main()
{
int arr1[10][10] = { 0 };
int arr2[10][10] = { 0 };
int n = 0;
int m = 0;
scanf("%d %d", &n, &m);
int i = 0;
int j = 0;
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
scanf("%d", &arr1[i][j]);
}
}
int flag = 1; //默认相同
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
scanf("%d", &arr2[i][j]);
if (arr1[i][j] != arr2[i][j])
{
flag = 0;
break;
}
}
}
if (flag == 1)
{
printf("Yes\n");
}
else
{
printf("No\n");
}
return 0;
}
9、矩阵转置
第一行包含两个整数n和m,表示一个矩阵包含n行m列,用空格分隔。 (1≤n≤10,1≤m≤10)
从2到n+1行,每行输入m个整数(范围-231~231-1),用空格分隔,共输入n*m个数,表示第一个矩阵中的元素。
输出描述:
输出m行n列,为矩阵转置后的结果。每个数后面有一个空格。
int main()
{
int n = 0;
int m = 0;
int arr[10][10] = { 0 };
scanf("%d %d", &n, &m);
int i = 0;
int j = 0;
//输入
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
scanf("%d", &arr[i][j]);
}
}
//转置输出
for (i = 0; i < m; i++) //打印3行2列
{
for (j = 0; j < n; j++)
{
printf("%d ", arr[j][i]);
}
printf("\n");
}
return 0;
}
short解引用
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5 };
short* p = (short*)arr;
int i = 0;
for (i = 0; i < 4; i++)
{
*(p + i) = 0;
}
for (i = 0; i < 5; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
1 2 3 4 5
short 解引用每次访问2个字节
00 00 3 3 5
10、VS小端存储
#include <stdio.h>
int main()
{
int a = 0x11223344;
char* pc = (char*)&a;
*pc = 0;
printf("%x\n", a);
return 0;
}
低位放在低地址 高位放在高地址
// 44 33 22 11
// %d - 10进制
// %o - 8进制
// %x - 16进制
11、sizeof返回
#include <stdio.h>
int i; //全局变量,没有给初始值时,编译其会默认将其初始化为0
int main()
{
i--; // -1
if (i > sizeof(i))
{
printf(">\n");
}
else
{
printf("<\n");
}
return 0;
}
sizeof - 返回的是无符号整数
i和sizeof(i)比较 算术转换 int强制类型转化为size_t
-1对应的无符号整形是一个非常大的数字
12、使用指针打印数组内容
写一个函数打印arr数组的内容,不使用数组下标,使用指针。
arr是一个整形一维数组
#include <assert.h>
void print(const int* p, int sz)
{
int i = 0;
assert(p);
for (i = 0; i < sz; i++)
{
printf("%d ", *(p + i));
}
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
//数组在内存中是连续存放的 只要知道起始位置 就能找到数组
print(arr, sz);
return 0;
}
12、计算求和
求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字,
例如:2+22+222+2222+22222
int main()
{
int i = 0;
int a = 0;
int tmp = 0;
int Sn = 0;
scanf("%d", &a);
for (i = 0; i < 5; i++)
{
tmp = tmp * 10 + a;
Sn = Sn + tmp;
}
printf("%d\n", Sn);
return 0;
}
13、求a的n项
int main()
{
int a = 0;
int n = 0;
int i = 0;
int sum = 0;
int k = 0;
scanf("%d %d", &a, &n);
for (i = 0; i < n; i++)
{
k = k * 10 + a;
sum += k;
}
printf("%d\n", sum);
return 0;
}
14、打印水仙花数
求出0~100000之间的所有“水仙花数”并输出。
“水仙花数”是指一个n位数,其各位数字的n次方之和确好等于该数本身,如:153=13+53+3^3,则153是一个“水仙花数”
判断i是否是自幂数
#include <math.h>
int main()
{
int i = 0;
for (i = 0; i <= 100000; i++)
{
int tmp = i; //计算位数后i会改变 用tmp求
//1. 计算i的位数 - n
int cnt = 1;
int sum = 0;
while (tmp /= 10)
{
cnt++;
}
//2. 计算i的每一位的n次方之后
tmp = i;
while (tmp)
{
sum += (int)pow(tmp % 10, cnt);
tmp /= 10;
}
//3. 判断
if (sum == i)
{
printf("%d ", i);
}
}
return 0;
}
求位数函数
#include <math.h>
int count(int tmp)
{
int cnt = 1;
while (tmp /= 10)
{
cnt++;
}
return cnt;
}
int main()
{
int i = 0;
for (i = 0; i <= 100000; i++)
{
int tmp = i;
//1. 计算i的位数 - n
int sum = 0;
int cnt = count(i);
//2. 计算i的每一位的n次方之后
while (tmp)
{
sum += (int)pow(tmp % 10, cnt);
tmp /= 10;
}
//3. 判断
if (sum == i)
{
printf("%d ", i);
}
}
return 0;
}
本文介绍了计算机程序中的bug概念及调试的重要性,详细讲解了Windows环境下调试的方法与技巧,包括使用各种快捷键、查看程序状态等。同时,文章还提供了多个调试实例,并探讨了常见编程错误及其分类,最后给出了编写高质量、易调试代码的建议。
3688

被折叠的 条评论
为什么被折叠?



