学C的第二十天【实用调试技巧:上期补充;5. 如何写出好(易于调试)的代码; 6. 编程常见的错误;练习:1. 类型转换 和 Unsigned int;2. 输入两个升序排列将两个序列合并为有序数列】-1

简介: 上期补充:在 Release 版本下,运行实例二(说明发布版本下对程序的优化)

上期补充:在 Release 版本下,运行实例二

(说明发布版本下对程序的优化)


6a2bd305f20e441d9b0aaf779afeb79e.png

5. 如何写出好(易于调试)的代码

                             

(1). 优秀的代码:

1. 代码运行正常

2. bug

3. 效率

4. 可读性

5. 可维护性

6. 注释清晰

7. 文档齐全

常见的coding(编码)技巧:

1. 使用assert断言

2. 尽量使用const赋予常属性,无法修改

3. 养成良好的编码风格

4. 添加必要的注释

5. 避免编码的陷阱(类似 标题4 中的 实例二)

(2). 示范一:模拟实现库函数:strcpy

                 

#include <stdio.h>
//模拟实现库函数:strcpy,把一个字符串赋给另一个字符串。
//形参 为 目标地址、被复制字符串地址
//返回值 为 char* :返回目标地址的首元素地址
//复制包括 结束符:“\0”
#include <assert.h>
void my_strcpy(char* dest, char* src)
{
  //如果 目标地址 是 NULL空指针 就会出问题
  //为防止出现空指针,可以设置 断言asset宏
  //断言(设置一个表达式,如果表达式为假则报错)
  assert(dest != NULL); //使用时要包含头文件 <assert.h>
  assert(src != NULL); 
  //括号中存放我们期待的结果(表达式),一旦表达式为假就会报错
  while (*src != '\0')
  //可以直接写成(*src),因为 \0 的ASCII码值为0,判定到0就跳出循环
  {
    *dest = *src; //把对应位置的src的值赋给dest
    //两指针移至下一位
    dest++;
    src++;
  }
  //当while循环到\0时,跳出循环,\0 还没有赋值给目标地址
  //所以跳出循环后要再赋值一次,把 \0 赋给目标地址
  *dest = *src;
}
int main()
{
  char arr1[] = "hello bit";
  char arr2[20] = "xxxxxxxxxxxxx";
  //char* p = NULL; //断言测试
  my_strcpy(arr2, arr1);
  printf("%s\n", arr2);
  //printf("%s\n", my_strcpy(arr2, arr1));
  //模仿的 strcpy 会返回目标地址的首元素地址 
  return 0;
}

5ec164e045864e6f92f017da526b8fa9.png

             

(进行优化:)

//版本2:
#include <stdio.h>
#include <assert.h>
//函数返回的是目标空间的起始地址
char* my_strcpy(char* dest, const char* src) //这里const放在*左边,限制了*src,但还可以使用src
// const:使具有 常属性 ,
//修饰指针时:
//当 const 放在 * 的左边时,限制的是 *p (指针指向内容),即 *p 不能被改变(不能通过指针变量改变指针的内容)
// 但是 p 是可以改变的(指针变量的本身是可以改变的)
//当 const 放在 * 的右边时,限制的是 p (指针变量本身),即 p (指针变量本身)不能被改变
// 但是 *p (指针内容)是可以通过指针来改变的
{
  char* ret = dest; //先把dest的首地址存起来,方便后面保存
  //因为之后赋值后,dest会后移,就不是首地址了
  //断言
  assert(dest != NULL);
  assert(src != NULL);
  while (*dest++ = *src++)
    ; //空语句
  //把赋值操作直接放在while的判定条件中
  //例如:把src中的 h 赋给 dest,此时表达式判定结果为 h
  // h 的ASCII码值 不为0,所以循环继续
  //当把 \0 赋给dest时,表达式结果为 0,停止循环
  //此时即把 \0 赋值了过去,又停止了 循环
  //使用后置++,先使用地址上的内容,再++,判定下一位
  //*dest++:先执行 *dest 解引用,之后再执行 dest++
  //直接把 while 的大括号给省了
  return ret;
}
int main()
{
  char arr1[] = "hello bit";
  char arr2[20] = "xxxxxxxxxxxxx";
  //char* p = NULL; //断言测试
  //my_strcpy(arr2, arr1);
  //printf("%s\n", arr2);
  printf("%s\n", my_strcpy(arr2, arr1)); 
  //模仿的 strcpy 会返回目标地址的首元素地址 
  //此时使用了 链式访问:一个函数的返回值 作为 另一个函数的返回值
  return 0;
}

image.png

知识点一:const

               

const:使具有 常属性“无法改变”

           
const 修饰指针

           
const 在 * 的左边时,限制的是 *p指针指向内容),即 *p不能被改变不能通过指针变量改变指针的内容),但是 p可以改变的(指针变量的本身是可以改变的)

const 在 * 的右边时,限制的是 p 指针变量本身),即 p指针变量本身不能被改变,但是 *p指针内容)是可以通过指针来改变

知识点二:使用断言 assert

image.png

知识点三:简化 字符串赋值流程

image.png

知识点四:链式访问

image.png

相关文章
|
22天前
|
Java 程序员 编译器
在Java编程中,保留字(如class、int、for等)是具有特定语法意义的预定义词汇,被语言本身占用,不能用作变量名、方法名或类名。
在Java编程中,保留字(如class、int、for等)是具有特定语法意义的预定义词汇,被语言本身占用,不能用作变量名、方法名或类名。本文通过示例详细解析了保留字的定义、作用及与自定义标识符的区别,帮助开发者避免因误用保留字而导致的编译错误,确保代码的正确性和可读性。
41 3
|
6月前
|
SQL 关系型数据库 MySQL
unsigned int 虽然mysql支持,但是不建议使用,因为可能在未来某个版本删除
unsigned int 虽然mysql支持,但是不建议使用,因为可能在未来某个版本删除
45 2
|
6月前
|
编译器 C++
C++_int负数转unsigned
C++_int负数转unsigned
58 0
|
6月前
|
Python
modelscope通义千问的14b量化版出错 说没有版本 这个代码都是从页面上粘贴下来的 Int8 Int4都试过了一样的错误?
modelscope通义千问的14b量化版出错 说没有版本 这个代码都是从页面上粘贴下来的 Int8 Int4都试过了一样的错误?modelscope.hub.errors.NoValidRevisionError: The model: qwen/Qwen-14B-Chat-Int4 has no valid revision!
542 1
|
6月前
|
存储 人工智能 编译器
learn_C_deep_5 (温故知新、sigend char a = -128的深度理解、unsigned int类型的写法规范)
learn_C_deep_5 (温故知新、sigend char a = -128的深度理解、unsigned int类型的写法规范)
|
6月前
|
存储 编译器 程序员
learn_C_deep_4 (类型和变量命名、sizeof(int) *p表示什么意思、原码、反码和补码的概念、计算机中数据计算时,为什么要转为二级制、unsigned和signed关键字)
learn_C_deep_4 (类型和变量命名、sizeof(int) *p表示什么意思、原码、反码和补码的概念、计算机中数据计算时,为什么要转为二级制、unsigned和signed关键字)
|
6月前
|
存储 C语言
学习总结(位操作符;循环输入的三种方式;交换两个变量值的三种方法;打印数字对应的二进制;unsigned int 与int 的区别;改变特定位数0/1;&&和||的连续操作(与前置,后置结合))
学习总结(位操作符;循环输入的三种方式;交换两个变量值的三种方法;打印数字对应的二进制;unsigned int 与int 的区别;改变特定位数0/1;&&和||的连续操作(与前置,后置结合))
66 0
|
存储 小程序 程序员
8k字详解整型(int)/字符型(char)/浮点型(float)/有符号(signed)/无符号(unsigned)数据在内存中的存储【程序员内功修炼/C语言】
8k字详解整型(int)/字符型(char)/浮点型(float)/有符号(signed)/无符号(unsigned)数据在内存中的存储【程序员内功修炼/C语言】
135 0
|
6月前
|
数据采集 分布式计算 数据处理
Dataphin常见问题之与指定类型int不兼容如何解决
Dataphin是阿里云提供的一站式数据处理服务,旨在帮助企业构建一体化的智能数据处理平台。Dataphin整合了数据建模、数据处理、数据开发、数据服务等多个功能,支持企业更高效地进行数据治理和分析。
|
6月前
|
SQL 流计算 OceanBase
OceanBase CDC从热OB库采集过来的Tinyint(1)类型会默认转换成Boolean,请教一下,如果想转换成int类型,有什方法么?
【2月更文挑战第25天】OceanBase CDC从热OB库采集过来的Tinyint(1)类型会默认转换成Boolean,请教一下,如果想转换成int类型,有什方法么?
163 3

热门文章

最新文章

下一篇
无影云桌面