文章目录
- 前言
- 一、调试
- 二、debug和release
- 三、调试需要多用,多熟悉
- 四、栈区底层简单介绍
- 五、优秀的代码:
- 常见的coding技巧:
- 六、const 修饰指针变量
- 1. const 出现在 * 左边
- 2. const 出现在 * 右边
- 七、strcpy函数的仿写
- 1.版本1
- 2. 版本2
- 3. 版本3
- 4. 版本4
- 总结
前言
VS调试、debug,release、栈区底层简单介绍,好的代码,以及const修饰指针变量以及strcpy函数的仿写
一、调试
调试的快捷键
- F5 启动调试,经常用来直接跳转到断点。
- F9 创建和取消断点。
- F10 一次执行一个过程,比如一个语句,一次函数的调用
- F11 一次执行一句话,会进入函数内部执行语句。
二、debug和release
- debug 通常是指调试版本。
- release 通常是发布版本,无法调试。
三、调试需要多用,多熟悉
- 调试很重要
- 据说,初学者80%写程序,20%调试(修bug),程序员20%写程序,80%调试.
四、栈区底层简单介绍
- 先看一个例子
- 这是在VS2019环境下的代码
- 此代码的结果是死循环,重复打印“hehe”。
#include <stdio.h>
int main()
{
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
for (i = 1; i <= 12; i++)
{
arr[i] = 0;
printf("hehe\n");
}
// i 与 arr 都是局部数据,都会放到栈区
// 栈区的使用习惯是先高地址,再低地址
// 所以,i 是 高地址, arr 是低地址
// 但是 arr 数组的下标是由低地址到高地址
// 所以给一定情况的越界,会导致 arr 和 i 的是同一个地址
// 所以 i 会不断地重置为0 ,会陷入死循环。
return 0;
}
- 内存分为 栈区,堆区,静态区
-
- 栈区内存的使用习惯是,先使用高地址空间,再使用低地址处的空间。
-
- 数组随着下标的增长地址是由低到高变化的。
-
- 如果i 和 arr之间由适当的空间,利用数组的越界操作就可能会覆盖到i,就可能会导致死循环出现的。
五、优秀的代码:
- 代码运行正常
- bug少
- 效率高
- 可读性高
- 可维护性高
- 注释清晰
- 文档齐全
常见的coding技巧:
- 使用assert
- 尽量使用const
- 养成良好的编码风格
- 添加必要的注释
- 避免编码的陷阱
六、const 修饰指针变量
1. const 出现在 * 左边
int main()
{
int a = 0;
int n = 0;
const int* p = &a;
//*p = 0; // err
p = &n; // right
reutrn 0;
}
- 如上代码
- const 出现在 * 左边,表示指针变量p所指向的对象不能通过变量p被修改。
- 但是,指针变量p可以重新取地址,不可以被修改。
2. const 出现在 * 右边
int main()
{
int a = 0;
int n = 0;
int* const p = &a;
*p = 0; // right
//p = &n; // err
reutrn 0;
}
- 如上代码
- const 出现在 * 右边,表示指针变量p所指向的对象可以通过变量p被修改。
- 但是,指针变量p不可以重新取地址,可以被修改。
七、strcpy函数的仿写
- strcpy库函数是会把字符串的**\0字符**也拷贝上的。
1.版本1
#include <stdio.h>
// strcpy函数的仿写
void my_strcpy(char* dect, char* ret)
{
while (*ret != '\0')// ret中若找到\0则跳出循环,此时*ret已经时\0,再次赋值就可以将\0也拷贝到dect中
{
*dect = *ret;
dect++;
ret++;
}
*dect = *ret;
}
int main()
{
char arr1[20] = "XXXXXXXXXXXXXX";
char arr2[] = "hello bit";
my_strcpy(arr1, arr2);
printf("%s", arr1);
return 0;
}
2. 版本2
#include <stdio.h>
// strcpy函数的仿写
void my_strcpy(char* dect, char* ret)
{
while (*ret != '\0')
{
*dect++ = *ret++;
}
*dect = *ret;
}
int main()
{
char arr1[20] = "XXXXXXXXXXXXXX";
char arr2[] = "hello bit";
my_strcpy(arr1, arr2);
printf("%s", arr1);
return 0;
}
3. 版本3
#include <stdio.h>
// strcpy函数的仿写
void my_strcpy(char* dect, char* ret)
{
while (*dect++ = *ret++)
{
;
}
}
int main()
{
char arr1[20] = "XXXXXXXXXXXXXX";
char arr2[] = "hello bit";
my_strcpy(arr1, arr2);
printf("%s", arr1);
return 0;
}
4. 版本4
- 考虑到如果用户传过来的不是指针
- 如果传入数据写反了等情况
#include <stdio.h>
#include <assert.h>
// strcpy函数的仿写
void my_strcpy(char* dect, const char* ret)
{
assert(dect != NULL);
assert(ret != NULL);
while (*dect++ = *ret++)// ret中若找到\0则跳出循环,此时*ret已经时\0,再次赋值就可以将\0也拷贝到dect中
{
;
}
}
int main()
{
char arr1[20] = "XXXXXXXXXXXXXX";
char arr2[] = "hello bit";
char p = NULL;
//my_strcpy(arr1, p); // 错误示例
//my_strcpy(arr2, arr1); // 会报错
my_strcpy(arr1, arr2);
printf("%s", arr1);
return 0;
}
总结
VS调试、debug,release、栈区底层简单介绍,好的代码,以及const修饰指针变量以及strcpy函数的仿写