• VS调试、debug和release、栈区底层简单介绍、const 修饰指针变量介绍



    前言

    VS调试、debug,release、栈区底层简单介绍,好的代码,以及const修饰指针变量以及strcpy函数的仿写

    一、调试

    调试的快捷键

    1. F5 启动调试,经常用来直接跳转到断点。
    2. F9 创建和取消断点。
    3. F10 一次执行一个过程,比如一个语句,一次函数的调用
    4. F11 一次执行一句话,会进入函数内部执行语句

    二、debug和release

    • debug 通常是指调试版本。
    • release 通常是发布版本,无法调试。

    三、调试需要多用,多熟悉

    • 调试很重要
    • 据说,初学者80%写程序,20%调试(修bug),程序员20%写程序,80%调试.

    四、栈区底层简单介绍

    • 先看一个例子
    • 这是在VS2019环境下的代码
    • 此代码的结果是死循环,重复打印“hehe”。
    #include 
    
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 内存分为 栈区,堆区,静态区
      1. 栈区内存的使用习惯是,先使用高地址空间,再使用低地址处的空间。
      1. 数组随着下标的增长地址是由低到高变化的。
      1. 如果i 和 arr之间由适当的空间,利用数组的越界操作就可能会覆盖到i,就可能会导致死循环出现的。

    在这里插入图片描述

    五、优秀的代码:

    1. 代码运行正常
    2. bug少
    3. 效率高
    4. 可读性高
    5. 可维护性高
    6. 注释清晰
    7. 文档齐全

    常见的coding技巧:

    1. 使用assert
    2. 尽量使用const
    3. 养成良好的编码风格
    4. 添加必要的注释
    5. 避免编码的陷阱

    六、const 修饰指针变量

    1. const 出现在 * 左边

     int main()
     {
     	int a = 0;
     	int n = 0;
     	const int* p = &a;
     	//*p = 0; // err
     	p = &n; // right
    	reutrn 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 如上代码
    • 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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 如上代码
    • const 出现在 * 右边,表示指针变量p所指向的对象可以通过变量p被修改。
    • 但是,指针变量p可以重新取地址,可以被修改。

    七、strcpy函数的仿写

    • strcpy库函数是会把字符串的**\0字符**也拷贝上的。

    1.版本1

    #include 
    //  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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    2. 版本2

    #include 
    //  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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    3. 版本3

    #include 
    //  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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    4. 版本4

    • 考虑到如果用户传过来的不是指针
    • 如果传入数据写反了等情况
    #include 
    #include 
    //  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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    总结

    VS调试、debug,release、栈区底层简单介绍,好的代码,以及const修饰指针变量以及strcpy函数的仿写

  • 相关阅读:
    Flutter中的StreamBuilder和FutureBuilder有什么区别
    uniapp地图手动控制地图scale
    展厅显示大屏怎么选,展厅使用哪种显示大屏好?
    c# 生成表达式树 - 动态表达式帮助类
    随机用户名获取易语言代码
    RabbitMQ--延迟队列--使用/原理
    [读论文]DECOR-GAN
    驱动开发 day3 9/12
    python ==True和is True有什么区别?(python单例对象True、False、None)(is和==和is)
    设计模式-状态模式(State)
  • 原文地址:https://blog.csdn.net/Farewell_me/article/details/138165119