5、C语言:结构

结构

  • 结构的基本知识
  • 结构与函数
    • 传递结构
  • 结构数组、指向结构的指针
  • 自引用结构(二叉树)
  • 表查找
  • 类型定义(typedef)
  • 联合
  • 位字段

结构也是一种数据类型。类似于int、char、double、float等。
结构是一个或多个变量的集合,这些变量可能为不同的类型,为了处理的方便而将这些变量组织在一个名字之下。
结构可以拷贝、赋值、传递给函数,函数也可以返回结构类型的返回值。

结构的基本知识

  • 关键字struct 引入结构声明。结构声明由包含在花括号内的一系列声明组成。
  • 关键字struct后面的名字是可选的,称为结构标记。结构标记用于为结构命名,在定义之后,结构标记就代表花括号内的声明,可以用它作为该声明的简写形式。
  • 结构中定义的变量称为成员。
struct point {int x;int y;
};
  • 结构中定义的变量称为成员。结构成员、结构标记和普通变量(即非成员)可以采用相同的名字,它们之间不会冲突,因为通过上下文分析总可以对它们进行区分。
  • 如果结构声明的后面不带变量表,则不需要为它分配存储空间,它仅仅描述了一个结构的模板或轮廓。
  • 结构的初始化可以在定义的后面使用初值表进行。
struct point maxpt = {320, 200};
  • 可以通过下列形式引用某个特定结构中的成员:结构名.成员
printf("%d,%d", pt.x, pt.y);
  • 结构可以嵌套。
struct rect {struct point pt1;struct point pt2;
};

结构与函数

结构的合法操作只有几种:作为一个整体复制和赋值,通过&运算符取地址,访问其成员。

传递结构

  1. 分别传递各个结构成员
  2. 传递整个结构(可采用函数返回值)
  3. 传递指向结构的指针
struct point *pp;

假定p 是一个指向结构的指针,可以用p->结构成员,这种形式引用相应的结构成员。

结构数组、指向结构的指针

下面两种类型相同:

struct key {char *word;int count;
};
struct key keytab[NKEYS];
struct key {char *word;int count;
} keytab[NKEYS];

自引用结构(二叉树)

用结构体来实现二叉树。

  • 结构体的自引用:
struct tnode { /* the tree node: */char *word; /* points to the text */int count; /* number of occurrences */struct tnode *left; /* left child */struct tnode *right; /* right child */
};
  • 两个结构相互引用
struct t {...struct s *p; /* p points to an s */
};
struct s {...struct t *q; /* q points to a t */
};

表查找

该算法采用的是散列查找方法——将输入的名字转换为一个小的非负整数,该整数随后将作为一个指针数组的下标。数组的每个元素指向某个链表的表头,链表中的各个块用于描述具有该散列值的名字。如果没有名字散列到该值,则数组元素的值为NULL。
在这里插入图片描述

链表中的每个块都是一个结构,它包含一个指向名字的指针、一个指向替换文本的指针以及一个指向该链表后继块的指针。如果指向链表后继块的指针为NULL,则表明链表结束。

struct nlist { /* table entry: */struct nlist *next; /* next entry in chain */char *name; /* defined name */char *defn; /* replacement text */
};

类型定义(typedef)

C语言提供了一个称为typedef的功能,它用来建立新的数据类型名.

typedef int Length;    //将Length定义为与int具有同等意义的名字。
typedef char* String;

typedef 中声明的类型在变量名的位置出现,而不是紧接在关键字typedef 之后。这里以大写字母作为typedef定义的类型名的首字母,以示区别。
从任何意义上讲,typedef 声明并没有创建一个新类型,它只是为某个已存在的类型增加了一个新的名称而已。
typedef 声明也没有增加任何新的语义:通过这种方式声明的变量与通过普通声明方式声明的变量具有完全相同的属性。实际上,typedef类似于#define 语句,但由于typedef 是由编译器解释的,因此它的文本替换功能要超过预处理器的能力。

typedef int (*PFI)(char *, char *);

该语句定义了类型PFI 是“一个指向函数的指针,该函数具有两个char *类型的参数,返回值类型为int”,它可用于某些上下文中。
除了表达方式更简洁之外,使用typedef还有另外两个重要原因。首先,它可以使程序参数化以提高程序的可移植性。如果typedef声明的数据类型同机器有关,那么,当程序移植到其它机器上时,只需改变typedef类型定义就可以了。一个经常用到的情况是,对于各种不同大小的整型值来说,都使用通过typedef 定义的类型名,然后,分别为各个不同的宿主机选择一组合适的short、int 和long 类型大小即可。
typedef 的第二个作用是为程序提供更好的说明性——Treeptr 类型显然比一个声明为指向复杂结构的指针更容易让人理解。

联合

联合是可以(在不同时刻)保存不同类型和长度的对象的变量,编译器负责跟踪对象的长度和对齐要求。联合提供了一种方式,以在单块存储区中管理不同类型的数据,而不需要在程序中嵌入任何同机器有关的信息。
联合的目的:一个变量可以合法地保存多种数据类型中任何一种类型的对象。

union u_tag {int ival;float fval;char *sval;
} u;

变量u 必须足够大,以保存这3 种类型中最大的一种,具体长度同具体的实现有关。这些类型中的任何一种类型的对象都可赋值给u,且可使用在随后的表达式中,但必须保证是一致的:读取的类型必须是最近一次存入的类型。

  • 访问联合中成员
    联合名.成员、 联合指针->成员
  • 联合使用
if (utype == INT)printf("%d\n", u.ival);
if (utype == FLOAT)printf("%f\n", u.fval);
if (utype == STRING)printf("%s\n", u.sval);
elseprintf("bad type %d in utype\n", utype);
  • 结构体中联合使用:与嵌套结构相同
struct {char *name;int flags;int utype;union {int ival;float fval;char *sval;
} u;
} symtab[NSYM];symtab[i].u.ival;

实际上,联合就是一个结构,它的所有成员相对于基地址的偏移量都为0,此结构空间要大到足够容纳最“宽”的成员,并且,其对齐方式要适合于联合中所有类型的成员。

  • 初始化
    联合只能用其第一个成员类型的值进行初始化,因此,上述联合u 只能用整数值进行初始化。

位字段

在存储空间很宝贵的情况下,有可能需要将多个对象保存在一个机器字中。

#define KEYWORD 01
#define EXTRENAL 02
#define STATIC 04enum { KEYWORD = 01, EXTERNAL = 02, STATIC = 04 };

C语言仍然提供了另一种可替代的方法,即直接定义和访问一个字中的位字段的能力,而不需要通过按位逻辑运算符。位字段(bit-field),或简称字段,是“字”中相邻位的集合。“字”(word)是单个的存储单元,它同具体的实现有关。

struct {
unsigned int is_keyword : 1;
unsigned int is_extern : 1;
unsigned int is_static : 1;
} flags;

字段的所有属性几乎都同具体的实现有关。字段是否能覆盖字边界由具体的实现定义。字段可以不命名,无名字段(只有一个冒号和宽度)起填充作用。特殊宽度0 可以用来强制在下一个字边界上对齐。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

12.3在应用层使用SPI总线

在SPI总线驱动框架中提供了一个spidev 的字符设备驱动,在应用层可以通过它来访问SPI总线。 应用层访问SPI总线的步骤 编写spidev设备树节点,在SPI总线的设备树节点下添加spidev设备的树节点,设备树示例如下所示: spidev0: spid…

Wargames与bash知识17

Wargames与bash知识17 Bandit25(Bandit26) 关卡提示 从bandit25登录到bandit26应该相当容易…用户bandit26的shell不是/bin/bash,而是其他东西。找出它是什么,它是如何工作的,以及如何摆脱它。 推荐命令 ssh, cat, …

STM32——高级定时器输出比较模式实验

1高级定时器输出比较模式实验 1.1高级定时器输出比较模式实验原理 1.2高级定时器输出比较模式实验实验配置步骤 1,配置定时器基础工作参数 HAL_TIM_OC_Init() 2,定时器PWM输出MSP初始化 HAL_TIM_OC_MspInit() 配置NVIC、CLOCK、GPIO等 3,配…

【面试突击】并发编程、线程池面试实战

🌈🌈🌈🌈🌈🌈🌈🌈 欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术 的推送 发送 资料 可领取 深入理…

C++进阶--红黑树

红黑树 一、红黑树的概念二、红黑树的性质三、红黑树结点的定义四、红黑树的插入五、红黑树的验证七、红黑树的查找七、红黑树与AVL树的比较七、完整代码RBTree.h 一、红黑树的概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色…

test-04-test case generate 测试用例生成 tcases 快速开始

拓展阅读 junit5 系列 基于 junit5 实现 junitperf 源码分析 Auto generate mock data for java test.(便于 Java 测试自动生成对象信息) Junit performance rely on junit5 and jdk8.(java 性能测试框架。性能测试。压测。测试报告生成。) 自动生成测试用例 入门指南 关于…

获取当前设备的IP

背景: 在本地使用自带webUI的项目时,需要制定webUI的访问地址。 一般本地访问使用:127.0.0.1,配置为可以从其他设备访问时,需要指定当前设备的IP,或者指定为0.0.0.0。 例如:使用locust的时候&a…

【蓝桥杯软件赛 零基础备赛20周】第7周——二叉树

文章目录 1 二叉树概念2 二叉树的存储和编码2.1 二叉树的存储方法2.2 二叉树存储的编码实现2.3 二叉树的极简存储方法 3 例题4 习题 前面介绍的数据结构数组、队列、栈,都是线性的,它们存储数据的方式是把相同类型的数据按顺序一个接一个串在一起。简单的…

腾讯云COS桶文件上传下载工具类

1&#xff0c;申请key和密钥 2&#xff0c;引入依赖 <dependency><groupId>com.qcloud</groupId><artifactId>cos_api</artifactId><version>5.6.24</version></dependency>3&#xff0c;工具类 package com.example.activi…

【学习iOS高质量开发】——熟悉Objective-C

文章目录 一、Objective-C的起源1.OC和其它面向对象语言2.OC和C语言3.要点 二、在类的头文件中尽量少引用其他头文件1.OC的文件2.向前声明的好处3.如何正确引入头文件4.要点 三、多用字面量语法&#xff0c;少用与之等价的方法1.何为字面量语法2.字面数值3.字面量数组4.字面量字…

QT上位机开发(进度条操作)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 进度条是一个比较常见的控件。如果某个操作需要很长的时间才能完成&#xff0c;那么这个时候最好有一个进度条提示&#xff0c;这样比较容易平复一…

CPT203-Software Engineering 笔记

Week 1 -- Introduction failure reason professional software development*** maintain, security, efficiency, acceptability two kinds***: generic, customized software deterioration 软件退化 reduce changes/ side effects after changes software engineering …

前端重置密码报错记录

昨天晚上&#xff0c;我写了重置密码的前端&#xff0c;测试的时候报错 今天上午&#xff0c;我继续试图解决这个问题&#xff0c;我仔细检查了一遍&#xff0c;前端没有问题 可以正常接收输入的数据并且提交 但是后端接收到的数据为空&#xff0c;后端接口也没有问题 但后端收…

Java SE入门及基础(12)

do-while 循环 1. 语法 do { //循环操作 } while ( 循环条件 ); 2. 执行流程图 3. 案例 从控制台录入学生的成绩并计算总成绩&#xff0c;输入0 时退出 4. 代码实现 public static void main ( String [] args ) { Scanner sc new Scanner ( System . in )…

【IDEA】瑞_IDEA模版注释设置_IDEA自动生成注释模版(详细图文步骤)

文章目录 1 概要2 类的自定义模版注释3 自定义模版注释3.1 方法的自定义模版注释3.2 属性的自定义模版注释 &#x1f64a; 前言&#xff1a;在Java开发中&#xff0c;注释具有不可或缺的重要性&#xff0c;注释负责解释代码&#xff0c;能帮助开发人员深入理解代码的逻辑和功能…

Vue2:通过ref获取DOM元素

一、场景描述 我们在页面的开发过程中&#xff0c;经常需要操作dom元素&#xff0c;来实现我们需要的效果。 以往js中&#xff0c;我们是通过给dom添加id&#xff0c;然后&#xff0c;通过js代码document来获取这个dom 简写代码案例&#xff1a; <h2 id"test"&…

Flutter之运行错误:this and base files have different roots

运行时报错&#xff1a; this and base files have different roots: E:\Demolpro\waqu\build\flutter-plugin-_android_lifecycle and C:\Users\78535\AppData\Local\Pub\Cache\hosted\pub.dev\flutter_pulgin_android_lifecycle-2.0.17\android 如图&#xff1a; 这种情况…

Java多线程并发篇----第十三篇

系列文章目录 文章目录 系列文章目录前言一、Semaphore 信号量二、Semaphore 与 ReentrantLock 区别三、可重入锁(递归锁)四、公平锁与非公平锁前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,…

力扣每日一练(24-1-13)

如果用列表生成式&#xff0c;可以满足输出的型式&#xff0c;但是不满足题意&#xff1a; nums[:] [i for i in nums if i ! val]return len(nums) 题意要求是&#xff1a; 你需要原地修改数组&#xff0c;并且只使用O(1)的额外空间。这意味着我们不能创建新的列表&#xff…

Asp .Net Core 系列: 集成 Consul 实现 服务注册与健康检查

文章目录 什么是 Consul?安装和运行 ConsulAsp .Net Core 如何集成 Consul 实现服务注册和健康检查Consul.AspNetCore 中的 AddConsul 和 AddConsulServiceRegistration 方法 究竟做了什么&#xff1f;AddConsul 方法AddConsulServiceRegistration 方法 配置 Consul 检查服务封…