结构体入门调试技巧

news2024/9/20 20:29:06

目录

前言:

一.结构体

1.1结构体的初始化和访问

二.结构体传参

三.调试技巧

3.1VS里的版本

3.2调试功能介绍

四.好代码

4.1const修饰指针的两种位置

五.错误分类


❤博主CSDN:啊苏要学习

  ▶专栏分类:C语言◀

  C语言的学习,是为我们今后学习其它语言打好基础,C生万物!

  开始我们的C语言之旅吧!✈


前言:

  结构体是很重要的C语言内容,打好结构体的基础是很有必要的另外,再把程序员必备的硬技能---调试技巧掌握好,可以让我们高效的找出bug的地方。调试就是在寻找使程序出现不符合预期的错误逻辑代码。

一.结构体

  结构体是用来描述有多种参数特征的复杂对象,比如描述一本书,有书名、有价格、作者、书号等但是如果只说书名,是描述不清楚的具体是哪一本书的---(也就是用一个字符数组)。用一个书的价格更不可能描述清楚~

  结构体使用的关键字是struct,和枚举类型(enum)一样,都是使用关键字创建一个新的数据类型;结构体成员可以是不同的数据类型

#include <stdio.h>

struct Book
{
    char author[7];
    char BookName[20];
    float Price;
    int ed;
}b2;//参数列表 在结构体后面可以创建该结构体类型的全局变量
int main()
{
    struct Book b1 = {"张三", "我的牢底生活", "55.5", 2};
}

  使用struct创建一个名为Book的结构体类型,在C++中,创建b1结构体变量的时候,不需要加struct,在C语言中struct不能省略在C语言想要这么做的话,可以typedef重命名一下,一般都会这么做,因为每次都要多写一个struct,不仅显的长,还麻烦

#include <stdio.h>

typedef struct Book
{
    //结构体成员 --- 成员列表
    char author[7];
    char BookName[20];
    float Price;
    int ed;
}Book;//Book和struct Book等效

//重命名和参数列表是不能一起表示的

int main()
{
    struct Book b1 = {"张三", "我的牢底生活", "55.5", 2};
}

1.1结构体的初始化和访问

  结构体的初始化和数组一样使用列表{}初始化,注意不能在创建结构体类型的时候给结构体成员初始化,因为它只是一个类型,是一张蓝图,并没有实际的空间只有在实例化(使用结构体类型创建结构体变量)才有分配空间

  结构体初始化有两种方式:第一种就是按照成员列表依次初始化;第二种就是不根据列表的顺序初始化,但第二种需要加上一些指定性的东西才能实现,请看代码: 

  在打印的时候,点操作符(.)是访问结构体成员的一种方式,使用结构体变量名.成员变量的方式访问所以在使用第二种方式初始化可以这样理解,.height其实就是在访问s2里的height成员,因为这是在初始化s2

  补充不要第一种方式和第二种方式混合使用

  结构体访问的两种方法:

  1. 第一种是前面提到的结构体变量.成员
  2. 第二种是结构体指针->成员

  第一种方法和第二种方法都行,第三种其实就是指针解引用拿到结构体变量,再使用第一种方法,duck不必~

二.结构体传参

  传值方式和传址方式

#include <stdio.h>

struct Stu
{
    char number[12];
    char name[10];
    int age;
    char address[50];
};
void Print1(struct Stu s1)
{
    printf("%s %s %d %s\n", s1.number, s1.name, s1.age, s1.address);
    s1.age = 70;
}
void Print2(struct Stu* ps)
{
    printf("%s %s %d %s\n", ps->number, ps->name, ps->age, ps->address);
    (*ps).age = 80;
}

int main()
{
    struct Stu s1 = {"1111", "张三", 23, "阿拉斯加"};
    Print1(s1);
    printf("%d\n", s1.age);
    Print2(&s1);
    printf("%d\n", s1.age);
    return 0;
}

  Print1是把s1这一整个变量传给形参,相比与传址而言,传值浪费空间严重,因为结构体本身是很大的,形参是实参的一份临时拷贝,传值会在栈区上开辟一模一样结构体s1而地址的大小无非就是4个或者8个字节

  第二就是传地址可以在函数内改变函数外部的变量,因为使用的是s1本身传值改变不了的原因是,形参是一块新的空间,改变不了原来的

  总结对于结构体,传地址可以节省空间,可以改变外部变量,一般情况下传的是结构体的地址

三.调试技巧

  调试的出现是为了解决程序的bug,这里不得不提一下计算机史上第一个bug的故事~

  起初,计算机占地很大,有一两个房间的大小,计算机前人在执行程序的时候,程序跑不过去,于是检查完逻辑,便跑到房间里寻找硬件哪里出错了,最后在一根晶体管里发现一只死去的虫子清理掉后,换了一根晶体管,程序就跑起来了,这个虫子引起的错误被称为bug,后来bug常用来描述代码运行错误,程序出错的情况

3.1VS里的版本

  在VS编译器里有可以调的生成可执行程序的版本,一个是Debug版本,一个是Release版本

  Debug版本是程序员在写代码时使用的,包含调试信息,可以进行调试,在大小,运行速度上不做任何优化。

  Release版本是发行版本,不包含调试信息,是测试人员测验程序满不满足客户要求,有没有存在隐藏性的致命bug等,也是客户使用的版本。编译器会对代码进行优化,使得下载的的大小少,运行速度快。

3.2调试功能介绍

  ctrl+f5是不调试执行,一口气跑完程序,也就是跑代码,运行起来

  fn+f9是打断点的功能,它配合fn+f5使用。当我们为某一行代码打上断点,再按fn+f5,会让程序的执行到断点处停下来但ctrl+f5遇到断点不会停下来,因为它是不调试执行还要需要注意的是,当没有断点的时候,fn+f5和ctrl+f5是一样的,因为没有断点拦住fn+f5

  补充如果读者的电脑没有取消fn这个功能键,就需要按fn+f5、fn+f9这样子,如果已经取消的读者,可以直接按f5表示调试执行,f9打断点。博主没有取消掉fn的功能键,所以需要按fn。

  fn+f10逐过程调试,代码一个过程一个过程的走,遇到调用函数也是直接执行完

  fn+f11是逐语句调试,代码一句一句的走,遇到调用函数会进入函数内部执行函数里的代码

  fn+f10或fn+f11或fn+f9搭配fn+f5都可以进入调试状态。进入调试状态后,就会激活窗口功能,就有以下的监视窗口

  我们来讲一些有用的窗口,有以下几个:

  自动窗口它会根据执行流的位置,自动在窗口监视相应变量的值,我们不需要自己手动输入变量名去观察。不过它只要过了这个执行流,它先前监视的那些变量也会自动消失

  局部窗口也是一样,观察执行的位置有那些局部变量,在窗口上显示,自动有,自动无,这两个不是很重要,最重要的是监视窗口。

  监视窗口是需要我们手动输入变量名,但它不会消失,会一直监视着,我们用的最多的就是监视窗口

  内存窗口可以看内存的存储情况。调用堆栈窗口可以看出函数的调用关系。寄存器窗口监视的是寄存器。反汇编窗口可以进入到反汇编,看汇编代码。

  栈的特性先使用高地址,再使用低地址

四.好代码

  好代码的一些公认的标准

  1. 代码运行正常;
  2. bug很少(有些bug是隐晦的,避免不了,尽量不要有bug);
  3. 效率高;
  4. 可读性高;
  5. 可维护性高;
  6. 注释清晰
  7. 有一些帮助文档帮助理解;

  怎么写出好代码

  • 使用assert(断言),确保不会出现我们最不期望的情况出现
  • 使用const关键字保护我们期望不要被修改的内容被修改
  • 添加注释,把写代码的逻辑写出来,方便自己也方便他人

  assert(exp1); assert的头文件是<assert.h>,如果exp1的表达式为真,那assert什么事情都不会做,如果表达式为假,就会报错,让程序跑不起来,并且很好的一点是,它会告诉你是在哪一个地方出错了

4.1const修饰指针的两种位置

  我们先看一种情况

  这里a被const修饰了,也就是说我们不期望a的内容被改变确实,不能直接通过a改变,但可以用指向a的指针去改变,这就有点像障眼法一样,用另一种巧妙的方式改变了a的值。当然编译器也会报警告。

  那该怎么做才能让指针改变不了a呢?在*的左边加上const修饰就可以了。 

  只要是在星号的左边放着,意思是const修饰的是*p,*p不能被改变,也就是p不能通过解引用改变它所指向的空间里的内容

  第二种情况是const放在*的右边,这样就会使pa不能更改

五.错误分类

  使用编译器跑代码的时候,会出现三种错误

  编译型错误一般是代码出现语法错误,这种情况很好解决,在编译器的报错栏里左键双击可以快速定位到行数,修改后即可

  链接型错误一般是程序找不到对应的变量名或函数名,也有可能是头文件没包含报的错,我们需要注意不要使用未定义的函数、变量,也有可能是在打字的时候多了后少了,大小写混了

  运行时错误以上两种情况都比较好处理,最难处理的属于运行错误了,表现为代码跑的起来,但结果是错误的,这时解决的方法有两种第一种是脑袋里过程序的执行逻辑,第二种就是调试找bug单纯仅凭直觉是不够的,除非已经见过太多的bug了,可以凭直觉预支到是哪一部分出错了,再进行小范围内调试

  好啦,以上就是C语言的基础啦,后面就讲更深层次的C语言知识了。对了,博主由于一次测试,被编程题折磨到了,痛定思痛,转向最弱的编程题进军,以后更多的是题目的更新,希望大家能够喜欢。

  小透露:博主的编程能力是真的差,差到那种,一些就都是bug的那种,最弱的地方最致命,痛苦。


结语:希望读者读完有所收获!在学C的路上,祝福我们能越来越C!✔

  读者对本文不理解的地方,或是发现文章在内容上有误等,请在下方评论区留言告诉博主哟~,也可以对博主提出一些文章改进的建议,感激不尽!最后的最后!

  ❤求点赞,求关注,你的点赞是我更新的动力,一起努力进步吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/565042.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

蓝桥杯2019年省赛——扫地机器人

题目描述 小明公司的办公区有一条长长的走廊&#xff0c;由 NN 个方格区域组成&#xff0c;如下图所示。 走廊内部署了 K 台扫地机器人&#xff0c;其中第 i 台在第Ai​ 个方格区域中。已知扫地机器人每分钟可以移动到左右相邻的方格中&#xff0c;并将该区域清扫干净。 请你…

Java企业级开发学习笔记(4.1)Spring Boot入门程序

该文章主要为完成实训任务&#xff0c;详细实现过程及结果见【http://t.csdn.cn/Qh554】 文章目录 一、使用Maven方式构建Spring Boot项目1.1 创建Maven项目1.2 添加依赖1.3 创建入口类1.4 创建控制器1.5 运行入口类1.6 访问Web页面1.7 修改访问映射路径1.8 定制启动标语1.8.1 …

UE5.1.1C++从0开始(10.作业三)

这次作业量和之前的相比可能会有点大&#xff0c;我先整理一下这次的作业清单&#xff1a; 魔法子弹的飞行声音以及爆炸声音给玩家增加受击的闪亮的效果&#xff0c;和立方体相同的那种增加一个health max的变量&#xff0c;把widget里头的health节点更换为health max节点&…

PythonOCR识别扫描版纯图PDF提取汉字的10大方法,力推RapidOCRPDF 可识别纯图PDF 加密签名的PDF 重点是开源免费,某些方面准确度比百度OCR高

下面实例都以下面的测试样例PDF为实验对象 非纯图可复制pdf 纯图PDF TOP1&#xff1a;RapidOCRPDF 可识别纯图PDF也能识别加密签名的PDF 重点是开源免费 https://github.com/RapidAI/RapidOCRPDF # 基于rapidocr_onnxruntime pip install rapidocr_pdf[onnxruntime]# 基于ra…

多体动力学:哈密尔顿原理的使用

参考资料&#xff1a; HAMILTON’S PRINCIPLE AND HAMILTON’S FORMULATION 原理已经讲得很详细了。如果看不到可以见我的资源&#xff0c;不用积分就可以下载。 步骤&#xff1a; 1.写出拉格朗日表达式 L T − V LT-V LT−V, T T T是系统的动能&#xff0c; V V V是系统的…

二进制安装1.26版本k8s(docker)

文章目录 前言准备工作准备4台虚拟机说明下载对应的二进制包初始化操作CentOS7配置yum源配置免密、修改hostname、关闭防火墙、selinux、关闭swap分区(方便后面进行其它操作)下载软件包并批量安装配置时间同步配置打开文件描述符添加ipvs模块和内核模块 Ubuntu配置apt源配置免密…

【数据结构】---堆排序+TOP-K问题(了解游戏排行底层原理)

文章目录 前言&#x1f31f;一、建堆的两种方式&#xff1a;&#x1f30f;1.1 向上调整建堆(堆排序)&#xff1a;&#x1f4ab;1.1.1 完整代码&#xff1a;&#x1f4ab;1.1.2 流程图(以小堆为例)&#xff1a;升序&#xff1a;建大堆&#x1f4ab;1.1.3 流程图(以小堆为例)&…

python调用海康视频汇聚平台API,获得所有摄像头设备编号、实时播放rtsp地址、回放rtsp地址

目录 1. 需求2. 思路3. 实现3.1. 确保服务器上安装视频汇聚平台&#xff08;iSecure Center&#xff09;3.2. 查看API网关是否安装成功3.3. 分配身份认证信息AK/SK3.4. 利用认证信息&#xff0c;python demo开发 1. 需求 海康视频汇聚平台(综合安防管理平台&#xff08;iSecur…

机器学习之集成学习

一、介绍 集成学习&#xff08;Ensemble Learning&#xff09;是一种机器学习技术&#xff0c;通过结合多个学习器&#xff08;例如决策树、神经网络、支持向量机等&#xff09;的预测结果&#xff0c;来达到更好的分类或回归预测性能。集成学习可以通过降低模型的方差&#x…

探究 Android 14 新功能之 TextView 搜索高亮和焦点移动~

前言 之前写的文章《Android 14 新功能之 HighLights》里&#xff0c;讲到 Android 14 里推出的 HighLights 新功能可以快速实现 TextView 文字的高亮效果&#xff0c;并支持动态更新。 本文将继续介绍 TextView 的另 2 处新功能&#xff1a; 使用 searchResultHighlight 等…

(转载)从0开始学matlab(第14天)—while循环结构

循环(loop) 是一种 matlab 结构&#xff0c;它允许我们多次执行一系列的语句。循环结构有两种基本形式 :while 循环和 for 循环。两者之间的最大不同在于代码的重复是如何控制的。在while 循环中&#xff0c;代码的重复的次数是不能确定的&#xff0c;只要满足用户定义的条件…

Metabase可视化BI系统部署安装及简单使用

metabase 是国外开源的一个可视化系统&#xff0c;语言使用了Clojure TypeScript。 Clojure&#xff08;/ˈkloʊʒər/&#xff09;是Lisp程式語言在Java平台上的現代、動態及函數式方言。来自维基百科。 我也是第一次看到这个语言&#xff0c;知道它是可以运行在Java环境上的…

脱离文档流和半脱离文档流(详解)

脱离文档流和半脱离文档流&#xff08;详解&#xff09;_脱离文档流是什么意思_大前端工程师的博客-CSDN博客 脱离文档流 脱离文档流是指&#xff0c;该元素脱离了文档中。不再占据默认分配的空间&#xff0c;它下面的元素会上去补位。 可以理解为脱离文档流的元素离开了它的座…

1720_Linux学习中的问题处理

全部学习汇总&#xff1a;GreyZhang/little_bits_of_linux: My notes on the trip of learning linux. (github.com) 这个有点学习的方法论的意思&#xff0c;画个滋味导图顺便整理一下。 遇到问题的时候&#xff0c;解决的方法大致有3中&#xff0c;而针对学习的建议有一部分是…

STL-queue和priority_queue的模拟实现

回顾 对于STL&#xff0c;我们已经知道了vector和list&#xff0c;而它们是STL中被称为六大组件之一的容器&#xff0c;我们还学习了模拟实现stack&#xff0c;而stack在STL中被称为六大组件之一的适配器&#xff0c;今天&#xff0c;我们来学习queue的模拟实现和priority_que…

分布式运用之ELK企业级日志分析系统

1.ELK的相关知识 1.1 ELK的概念与组件 ELK平台是一套完整的日志集中处理解决方案&#xff0c;将 ElasticSearch、Logstash 和 Kiabana 三个开源工具配合使用&#xff0c; 完成更强大的用户对日志的查询、排序、统计需求。 ElasticSearch&#xff1a; 是基于Lucene&#xff0…

Tomcat服务器、Servlet生命周期、上传下载文件、使用XHR请求数据、注解使用

文章目录 Servlet认识Tomcat服务器使用Maven创建Web项目创建Servlet探究Servlet的生命周期解读和使用HttpServletWebServlet注解详解使用POST请求完成登陆上传和下载文件下载文件上传文件 使用XHR请求数据重定向与请求转发重定向请求转发 ServletContext对象初始化参数 Servlet…

基于自营配送模式的车辆路径规划设计与实现_kaic

摘要 近年来&#xff0c;随着我国消费水平逐渐提升&#xff0c;消费者在网上购物的频率也越来越高&#xff0c;电商发展速度迅猛&#xff0c;加大了物流配送的压力&#xff0c;促使物流企业以更大的运力&#xff0c;更短的时间将货物送达。在货品的运输过程中&#xff0c;成本居…

TCP 连接未必都是用TCP协议沟通

确实&#xff0c;一般来说 TCP 连接是标准的 TCP 三次握手完成的&#xff1a; 1.客户端发送 SYN&#xff1b; 2.服务端收到 SYN 后&#xff0c;回复 SYNACK&#xff1b; 3.客户端收到 SYNACK 后&#xff0c;回复 ACK。 SYN 会在两端各发送一次&#xff0c;表示“我准备好了&…

MicroBlaze系列教程(9):xilisf串行Flash驱动库的使用

文章目录 1. xilisf库简介2. xilisf库函数3. xilisf配置4. xilisf应用示例工程下载本文是Xilinx MicroBlaze系列教程的第9篇文章。 1. xilisf库简介 xilisf库(Xilinx In-system and Serial Flash Library) 是Xilinx 提供的一款串行Flash驱动库,支持常用的 Atmel 、Intel、S…