5、C语言:结构

news2024/11/24 11:28:10

结构

  • 结构的基本知识
  • 结构与函数
    • 传递结构
  • 结构数组、指向结构的指针
  • 自引用结构(二叉树)
  • 表查找
  • 类型定义(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);
else
	printf("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 04

enum { 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.coloradmin.cn/o/1373976.html

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

相关文章

SG-8101CGA 系列 (晶体振荡器 可编程 可用 +125°C )

SG-8101CGA是可编程晶体振荡器,具有CMOS输出,适用于汽车,同时,该系列还提供相同的频率和其他参数的轻松编程能力,符合AEC-Q100标准,具有出色的电磁兼容性和稳定性,可以在各种环境下使用。外部尺…

判断质数-- 试除法判定质数(终于有人给我说明白了)

目录 判断质数思路:代码 原题链接 判断质数 给定 n个正整数 ai,判定每个数是否是质数。 输入格式 第一行包含整数 n 。 接下来 n 行,每行包含一个正整数 ai 。 输出格式 共 n 行,其中第 i 行输出第 i 个正整数 ai 是否为质数&…

社交距离 - 华为OD统一考试

OD统一考试(C卷) 分值: 200分 题解: Java / Python / C++ 题目描述 疫情期间,需要大家保证一定的社交距离,公司组织开交流会议,座位有一排共N个座位,编号分别为[0…N-1],要求员工一个接着一个进入会议室,并且可以在任何时候离开会议室。 满足:每当一个员工进入时,…

虚拟主机 如何上传大于100M的文件 php网站程序

问题 虚拟主机上传文件大小限制100m, 有时会遇到非常大的文件上传,上传过程中耗时非常久, 可能服务器的限制设置了上传文件尺寸,返回“413 request entity too large” 整体逻辑 前端:上传文件时,进行文…

vue前端开发自学,组件的嵌套关系demo

vue前端开发自学,组件的嵌套关系demo!今天开始分享的,前端开发经常用到的,组件的嵌套关系案例代码。下面先给大家看看,代码执行效果。 如图,这个是代码执行后,的效果布局! 下面给大家贴出来源码。方便大家…

C++_vector类

目录 一、vector的模拟实现 1、vector的组成结构 2、vector尾插数据 2.1 析构函数 3、迭代器实现 4、resize 5、删除数据 5.1 迭代器失效 6、指定位置插入数据 6.1 迭代器失效 7、迭代器构造和resize构造 8、深浅拷贝 结语: 前言: vect…

Vue3:使用解构赋值来读取对象里的键-值对(值也是对象)

一、前言 在Vue3中,想要读取一个对象的“键—值”对(值也是一个对象),数据格式如下: {1:{courseName: 课程1, study: 951526, visit: 3785553},2:{courseName: 课程2, study: 181630, visit: 380830}&…

Open CV 图像处理基础:(五)Java 使用 Open CV 的绘图函数

Java 使用 Open CV 的绘图函数 使用 Open CV 在 Java 中对图片使用绘图函数,分别绘制矩形、斜线、圆形、椭圆形以及添加文本 Java 使用 Open CV 的绘图函数 Java 使用 Open CV 的绘图函数函数绘制矩形绘制线绘制圆形绘制椭圆添加文本 代码示例 函数 绘制矩形 Im…

创新工具:2024年开发者必备的一款表格控件

前言 在现代工作环境中,信息的处理和管理是至关重要的。表格是一种常见的数据呈现和整理工具,被广泛应用于各行各业。然而,随着技术的不断发展,市场对表格控件的需求也越来越高。随着工作效率的重要性日益凸显,一款高…

卢森堡市场开发攻略,带你走进全球最富有的国家

卢森堡位于西欧,位于欧洲的十字路口,地理位置非常重要。卢森堡是高度发达的资本主义国家,人均gdp全球最高,是当之无愧的全球最富国家。卢森堡对外开放度高,很多产品依赖进口,也是一个非常不错的市场&#x…

Qt/Qt Creator窗体界面集成自定义类Ribbon工具栏-代码自定义实现-非第三方工具插件

程序示例精选 Qt/Qt Creator窗体界面集成自定义类Ribbon工具栏-完全代码自定义实现-非第三方工具插件 如需安装运行环境或远程调试,见文章底部个人QQ名片,由专业技术人员远程协助! 前言 这篇博客针对《Qt/Qt Creator窗体界面集成自定义类Ri…

小红书复盘思路总结,达人笔记投放规划

完成了一次小红书投放,是否任务就结束了?事实并非如此,投放的过程很重要的,但投放结束之后的复盘更重要。今天,我们针对小红书复盘思路总结,达人笔记投放规划!和大家来分享下。 小红书复盘思路主要可以分为…

计算数学表达式的程序(Java课程设计)

1. 课设团队介绍 团队名称 团队成 员介绍 任务分配 团队成员博客 XQ Warriors 徐维辉 负责计算器数据的算法操作,如平方数、加减乘除,显示历史计算记录 无 邱良厦(组长) 负责计算器的图形设计,把输入和结果显…

Python - Bert-VITS2 语音推理服务部署

目录 一.引言 二.服务搭建 1.服务配置 2.服务代码 3.服务踩坑 三.服务使用 1.服务启动 2.服务调用 3.服务结果 四.总结 一.引言 上一篇文章我们介绍了如果使用 conda 搭建 Bert-VITS2 最新版本的环境并训练自定义语音,通过 1000 个 epoch 的训练&#xf…

pandas笔记:找出在一个dataframe但不在另一个中的index

1 问题描述 假设我们有两个dataframe(这一段代码)来自transbigdata 笔记:官方文档案例1(出租车GPS数据处理)-CSDN博客 data tbd.clean_outofshape(data, sz, col[Lng, Lat], accuracy500) data data2 tbd.clean_ta…

Python爬虫之Scrapy框架系列(24)——分布式爬虫scrapy_redis完整实战【XXTop250完整爬取】

目录: 1.使用分布式爬取XX电影信息(1)settings.py文件中的配置:(2)spider文件的更改:(3)items.py文件(两个项目一致!):&am…

回归预测 | Matlab基于CPO-BP基于冠豪猪算法优化BP神经网络的数据多输入单输出回归预测

回归预测 | Matlab基于CPO-BP基于冠豪猪算法优化BP神经网络的数据多输入单输出回归预测 目录 回归预测 | Matlab基于CPO-BP基于冠豪猪算法优化BP神经网络的数据多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.CPO-BP回归基于冠豪猪优化算法[24年新…

产品使用说明书也能进行SEO?要怎么制作才能使其易于搜索?

产品使用说明书也能进行SEO?是的,你没有听错,不过是在线化的产品使用说明书。产品使用说明书能通过特定的策略和技巧进行搜索引擎优化(SEO)。这不只是为了让产品信息更易被找到,更是为了提升品牌知名度和用…

【Linux】应用与驱动交互及应用间数据交换

一、应用程序与 Linux 驱动交互主要通过以下几种方式: 1. 系统调用接口(System Calls): 应用程序可以通过系统调用,如 open(), read(), write(), ioctl(), 等来与设备驱动进行交互。这些调用最终会通过内核转发到相应的驱动函数…

【分布式微服务专题】从单体到分布式(四、SpringCloud整合Sentinel)

目录 前言阅读对象阅读导航前置知识一、什么是服务雪崩1.1 基本介绍1.2 解决方案 二、什么是Sentinel2.1 基本介绍2.2 设计目的2.3 基本概念 三、Sentinel 功能和设计理念3.1 流量控制3.2 熔断降级3.3 系统负载保护 四、Sentinel 是如何工作的 笔记正文一、简单整合Sentinel1.1…