标题C语言入门学习笔记(VS环境和调试技巧)
Debug和Release的区别:
Debug通常称为调试版本,包含调试信息并且不作优化,便于程序员调试程序
Release称为发布版本,进行了优化,使程序在代码大小和运行速度上都是最优的,以便客户使用。
调试技巧:
优秀的代码:
1、代码运行正常
2、bug很少
3、效率高
4、可读性高
5、可维护性高
6、注释清晰
7、文档齐全
常见的coding技巧
1、使用assert
2、尽量使用const
3、养成良好的编码风格
4、添加必要的注释
5、避免代码的陷阱
优化代码举例(模拟实现strcpy)
以下代码模拟实现函数strcpy的功能,但是有优化空间(很矬,把’\0’和"bit"的拷贝分开来了)
初始代码
#include<stdio.h>
#include<string.h>
#include<assert.h>
void my_strcpy(char* dest, char* str)
{
while (*str!='\0')
{
*dest=*str;
dest++;
str++;
}
*dest = *str;//此时*str是'\0'
}
int main()
{
//strcpy 字符串拷贝
char arr1[] = "#######";
char arr2[] = "love";
my_strcpy(arr1,arr2);
printf("%s\n",arr1);
return 0;
}
优化第一次
void my_strcpy(char* dest, char* str)
{
assert(dest != NULL);
assert(str != NULL);//断言,如果括号里的式子判断为假就会报错并且提示到行
while (*dest++ = *str++)
{
;
}
}
int main()
{
//strcpy 字符串拷贝
char arr1[] = "#######";
char arr2[] = "love";
my_strcpy(arr1,arr2);
printf("%s\n",arr1);
return 0;
}
如果dest和str搞反了,在某些情况下运行成功之后只能通过调试找到问题
优化第二次
优化:在调用的源值(str)类型前面加上const修饰,str如果被修改就会报错,就可以避免dest和str写反导致功能实现反了。
#include<stdio.h>
#include<string.h>
#include<assert.h>
void my_strcpy(char* dest, const char* str)//加上const
{
assert(dest != NULL);
assert(str != NULL);//断言,如果括号里的式子判断为假就会报错并且提示到行
while (*dest++ = *str++)
{
;
}
}
int main()
{
//strcpy 字符串拷贝
char arr1[] = "#######";
char arr2[] = "love";
my_strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
拓展 const:
const int *p//const int *p 修饰的是*p,也就是不能通过p改变*p的值
int* const p//int * const p 修饰的是p,就是不能改变指针变量p的地址
优化第三次
再次优化: 给函数设置返回类型char* ,然后返回dest的首地址(用指针ret指向),这样my_strcpy也可以用作别的函数的参数。
#include<stdio.h>
#include<string.h>
#include<assert.h>
char * my_strcpy(char* dest, const char* str)//加上const
{
char* ret = dest;//通过ret指向dest,最后可以通过返回ret来直接返回dest的首地址
assert(dest != NULL);
assert(str != NULL);//断言,如果括号里的式子判断为假就会报错并且提示到行
while (*dest++ = *str++)//把str的字符串拷贝到dest指向的空间,包含'\0'
{
;
}
return ret;
}
int main()
{
//strcpy 字符串拷贝
char arr1[] = "#######";
char arr2[] = "love";
printf("%s\n", my_strcpy(arr1, arr2));
return 0;
}
死循环(堆栈、越界访问)
该代码在某些编译器中运行结果为死循环,一直打印"hehe"(vs2019直接走不了)
int main()
{
int i=0;
int arr[10]={1,2,3,4,5,6,7,8,9,10};
for (i=0;i<=12;i++)
{
printf("hehe\n");
arr[i]=0;
}
system("pause");
return 0;
}
图解(图片引自 B站比特鹏哥) 很详细
当i=10的时候,就越界访问(非法)了,但是可以为arr[10]赋值为0
当i=12时刚好访问到i的地址(内存布局不同结果不同),这样i就等于0了,然后就会造成死循环。
注:本篇笔记是在B站比特鹏哥视频学习后结合个人理解写下的笔记,视频知识点远多于笔记内容,如有错误请指出,谢谢!