当前位置: 首页 > news >正文

C语言的结构体与联合体

引言

C语言提供了结构体和联合体两种聚合数据类型,使得程序员可以创建包括多个数据类型的复杂数据结构。结构体用于将不同类型的数据组合成一个单元,而联合体用于在同一存储空间中存储不同类型的数据。本篇文章将详细介绍C语言中的结构体和联合体,包括其定义、初始化、访问方法、内存对齐及使用场景。

一、结构体概述

结构体(struct)是一种用户自定义的数据类型,可以将不同类型的数据组合成一个整体。结构体是C语言中定义复杂数据类型的基本方法之一。

1. 结构体的定义与声明

结构体的定义关键字为struct,具体形式如下:

struct 结构体名称 {数据类型 成员名;数据类型 成员名;//...
};

示例代码:

#include <stdio.h>struct Person {char name[50];int age;float height;
};int main() {struct Person person1;return 0;
}

在上面的示例中,Person结构体包含nameageheight三个成员。

2. 结构体变量的初始化

结构体变量可以通过指定初始值进行初始化,也可以使用赋值操作进行逐个成员的初始化。

示例代码:

#include <stdio.h>struct Person {char name[50];int age;float height;
};int main() {// 通过列表初始化struct Person person1 = {"John", 30, 1.75};// 逐个初始化struct Person person2;person2.age = 25;person2.height = 1.80;printf("Name: %s, Age: %d, Height: %.2f\n", person1.name, person1.age, person1.height);return 0;
}

3. 结构体成员的访问

结构体成员通过点运算符(.)或箭头运算符(->)进行访问。

示例代码:

#include <stdio.h>struct Person {char name[50];int age;float height;
};int main() {struct Person person = {"Alice", 28, 1.68};struct Person *personPtr = &person;// 通过点运算符访问printf("Name: %s, Age: %d, Height: %.2f\n", person.name, person.age, person.height);// 通过箭头运算符访问printf("Name: %s, Age: %d, Height: %.2f\n", personPtr->name, personPtr->age, personPtr->height);return 0;
}

二、联合体概述

联合体(union)与结构体类似,但其所有成员共用相同的内存空间。联合体用于节省内存空间,可以在不同时间存储不同的数据类型。

1. 联合体的定义与声明

联合体的定义关键字为union,具体形式如下:

union 联合体名称 {数据类型 成员名;数据类型 成员名;//...
};

示例代码:

#include <stdio.h>union Data {int i;float f;char str[20];
};int main() {union Data data;return 0;
}

在上面的示例中,Data联合体包含整数i、浮点数f和字符数组str三个成员。

2. 联合体变量的初始化

联合体变量同样可以通过指定初始值进行初始化,也可以使用赋值操作进行逐个成员的初始化。

示例代码:

#include <stdio.h>union Data {int i;float f;char str[20];
};int main() {union Data data;// 赋值第一个成员data.i = 10;printf("data.i = %d\n", data.i);// 赋值第二个成员data.f = 220.5;printf("data.f = %.1f\n", data.f);// 赋值第三个成员strcpy(data.str, "C Programming");printf("data.str = %s\n", data.str);return 0;
}

3. 联合体成员的访问

联合体成员的访问也通过点运算符或箭头运算符进行。

示例代码:

#include <stdio.h>
#include <string.h>union Data {int i;float f;char str[20];
};int main() {union Data data;// 赋值第一个成员data.i = 10;printf("data.i = %d\n", data.i);// 赋值第二个成员data.f = 220.5;printf("data.f = %.1f\n", data.f);// 赋值第三个成员strcpy(data.str, "C Programming");printf("data.str = %s\n", data.str);return 0;
}

三、内存对齐与结构对齐

内存对齐是指数据在内存中的地址必须是某个特定的对齐倍数,以提高内存访问速度。C语言中的结构体会根据成员大小和顺序进行内存对齐。

1. 结构体对齐

示例代码:

#include <stdio.h>struct Example {char c;int i;
};int main() {printf("Size of struct Example: %zu\n", sizeof(struct Example)); // 输出16(假设4字节对齐)return 0;
}

上面的示例中,struct Example的大小可能超过其各成员大小之和,这是因为内存对齐。

2. 联合体对齐

联合体的内存对齐由其最大成员决定,所有成员共享同一内存地址。

示例代码:

#include <stdio.h>union Example {char c;int i;
};int main() {printf("Size of union Example: %zu\n", sizeof(union Example)); // 输出最大成员大小(假设4字节)return 0;
}

四、结构体和联合体的应用场景

1. 结构体

结构体用于组织和管理复杂的数据结构,常用于描述实体和事件,如学生信息、员工记录、日期和时间等。

示例代码:

#include <stdio.h>struct Date {int day;int month;int year;
};int main() {struct Date today = {15, 6, 2024}; printf("Today's date is: %d/%d/%d\n", today.day, today.month, today.year);return 0;
}

2. 联合体

联合体用于节省内存空间,常用于需要在同一存储空间中存储不同类型数据的场景,如定义网络数据包、实现不同类型的存储数据等。

示例代码:

#include <stdio.h>
#include <string.h>union NetworkPacket {int header;char data[20];
};int main() {union NetworkPacket packet;packet.header = 0x1A2B3C4D;printf("Header: %X\n", packet.header);strcpy(packet.data, "Hello, World!");printf("Data: %s\n", packet.data);return 0;
}

总结

C语言的结构体与联合体提供了组织和管理复杂数据结构的有效手段。通过结构体可以将不同类型的数据组合在一起,创建更为复杂和有意义的数据类型。此外,联合体可以高效地利用内存空间,使得不同的成员共享同一内存地址。通过理解和掌握结构体与联合体,程序员可以编写出更加模块化、可维护性和高效的C语言代码。

表格总结

结构体与联合体比较

特性结构体(struct)联合体(union)
内存分配各成员独立分配内存所有成员共享同一内存地址
使用场景管理复杂数据结构节省内存空间,存储不同类型数据
内存对齐按成员定义顺序对齐按最大成员对齐
结构体与联合体定义与访问示例
类型定义语法初始化与访问示例
结构体struct struct_name { ... }struct Person person = { ... }; person.age
联合体union union_name { ... }union Data data; data.i = 10

总结

C语言的结构体和联合体提供了组织和管理复杂数据结构的有效手段。通过结构体,可以将不同类型的数据组合在一起,创建更为复杂和有意义的数据类型。而联合体则通过共享同一内存地址,提供了一种高效利用内存的方式。理解和掌握结构体与联合体,不仅能够编写模块化、可维护和高效的代码,还能在特定场景下显著优化程序的内存使用。这些知识是深入学习和应用C语言的基础,高效利用这些特性将有助于解决实际编程中的复杂问题。

相关文章:

C语言的结构体与联合体

引言 C语言提供了结构体和联合体两种聚合数据类型&#xff0c;使得程序员可以创建包括多个数据类型的复杂数据结构。结构体用于将不同类型的数据组合成一个单元&#xff0c;而联合体用于在同一存储空间中存储不同类型的数据。本篇文章将详细介绍C语言中的结构体和联合体&#x…...

React Hooks小记(三)_forwardRef

forwardRef 【写在前面】 ​ 1、ref 的作用是获取实例&#xff0c;但由于函数组件不存在实例&#xff0c;因此无法通过 ref 获取函数组件的实例引用&#xff0c;而 React.forwardRef 就是用来解决这个问题的。 ​ 2、React.forwardRef 会创建一个 React 组件&#xff0c;这个组…...

面试复习记录

六级终于结束了&#xff0c;之前背的八股几乎也忘得差不多了&#xff0c;今天开始继续准备秋招&#xff0c;以下是每天的安排&#xff0c;会按时更新&#xff0c;就当是一种对自己的督促&#xff0c;也欢迎小伙伴们一起来互相监督。 2024.6.16 力扣&#xff1a;sql基础题库50…...

块级元素与行内元素详解

在网页设计与开发中&#xff0c;元素根据其在页面布局中的表现可分为两大类&#xff1a;块级元素&#xff08;Block-level Elements&#xff09;和行内元素&#xff08;Inline Elements&#xff09;。理解它们的特性和使用规则对于构建结构清晰、布局合理的网页至关重要。 块级…...

Kotlin编程实践-【Java如何调用Kotlin中带默认值参数的函数】

问题 如果你有一个带有默认参数值的 Kotlin 函数&#xff0c;如何从 Java 调用它而无须为每个参数显式指定值&#xff1f; 方案 为函数添加注解JvmOverloads。 也就是为Java添加重载方法&#xff0c;这样Java调用Kotlin的方法时就不用传递全部的参数了。 示例 在 Kotlin …...

中国城市统计年鉴(1985-2023年)

数据年限&#xff1a;1985-2023 数据格式&#xff1a;pdf、excel 数据内容&#xff1a;共分四个部分 第一部分是全国城市行政区划&#xff0c;列有不同区域、不同级别的城市分布情况&#xff1b; 第二、三部分分别是地级以上城市统计资料和县级城市统计资料&#xff0c;具体包括…...

RestTemplate远程请求的艺术

1 简说 编程是一门艺术,追求优雅的代码就像追求优美的音乐。 很多有多年工作经验的开发者,在使用RestTemplate之前常常使用HttpClient,然而接触了RestTemplate之后,却愿意放弃多年相处的“老朋友”,转向RestTemplate。那么一定是RestTemplate有它的魅力,有它的艺术风范。…...

Spring 整合 MyBatis 底层源码解析

大家好&#xff0c;我是柳岸花开。今天我们要讲的是 Spring 整合 MyBatis 的底层源码解析。希望大家能更深入理解 Spring 和 MyBatis 的整合原理&#xff0c;并应用到实际项目中。 由很多框架都需要和Spring进行整合&#xff0c;而整合的核心思想就是把其他框架所产生的对象放到…...

LeetCode 189.轮转数组

1.这个题我用的方法比较巧妙&#xff0c;大家如果觉得好的话&#xff0c;就给个免费的赞吧^ _ ^,谢谢了。 void reverse(int* nums,int left,int right) {while(left < right){int a nums[left];nums[left] nums[right];nums[right] a;left;right--;} } void rotate(int…...

JDK17 你的下一个白月光

JDK版本升级的非常快&#xff0c;现在已经到JDK20了。JDK版本虽多&#xff0c;但应用最广泛的还得是JDK8&#xff0c;正所谓“他发任他发&#xff0c;我用Java8”。 但实际情况却不是这样&#xff0c;越来越多的java工程师拥抱 JDK17&#xff0c;于是了解了一下 JDK17新语法&a…...

springboot优雅shutdown时如何保障异步线程的安全

我前面写了一篇springboot优雅shutdown的文章&#xff0c;看起来一切很美好。 https://blog.csdn.net/chenshm/article/details/139640775 那是因为没有进行多线程测试。如果一个请求中包括阻塞线程&#xff08;主线程&#xff09;和非阻塞线程&#xff08;异步线程&#xff09…...

C++格式化库fmt使用方法

1. 格式化库fmt简介 fmt github地址 api说明 格式化参数说明 内容的格式化&#xff0c;体现在代码中主要表现为字符串、基本类型、自定义类型的拼接。例如说打印日志、拼接变量等。C中我们会经常使用类似printf,snprintf(C风格使用不方便),std::string.append(繁琐), std::io…...

HTML 颜色名:网页设计的调色板

HTML 颜色名:网页设计的调色板 在网页设计和开发中,颜色是一个关键元素,它不仅影响视觉效果,还能传达情感和品牌信息。HTML 颜色名是用于在 HTML 和 CSS 代码中指定颜色的预定义名称。这些颜色名易于记忆,方便设计师和开发者快速选择和应用颜色。本文将详细介绍 HTML 颜色…...

12306 火车票价格解析 (PHP 解析)

1. 从接口拿数据 日期 出发站 终点站 都填上 xxx/otn/leftTicketPrice/queryAllPublicPrice?leftTicketDTO.train_date2024-06-15&leftTicketDTO.from_stationBJP&leftTicketDTO.to_stationSJP&purpose_codesADULT 返回的数据是这样的 {"validateMess…...

了解统计学中不同类型的分布

目录 一、说明 二、均匀分布&#xff1a; 三、机器学习和数据科学中的均匀分布示例&#xff1a; 3.1 对数正态分布&#xff1a; 3.2 机器学习和数据科学中的对数正态分布示例&#xff1a; 四、 帕累托分布 4.1 什么是幂律&#xff1f; 4.2 机器学习和数据科学中的帕累托分布示例…...

k8s-CCE创建工作负载变量引用

CCE创建工作负载变量引用 背景&#xff0c;看到cce创建负载时会生成变量&#xff0c;如下。在skywaking-agent的使用&#xff0c;想要调用cce负载变量生成service_name。 -Dskywalking.agent.authentication里含有敏感信息需要写到配置项。简单粗糙的都写到配置项好像不合适。…...

后端主流框架--Spring02

前言:上篇关于Spring的文章介绍了一些Spring的基本知识&#xff0c;此篇文章主要分享一下如何配置Spring环境&#xff0c;如何注入等。 Spring项目构建 导入Spring相关JAR包 <dependency><groupId>org.springframework</groupId><artifactId>spring…...

[数据集][目标检测]减速带检测数据集VOC+YOLO格式5400张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;5400 标注数量(xml文件个数)&#xff1a;5400 标注数量(txt文件个数)&#xff1a;5400 标注…...

分析Linux操作指令及使用场景与频率分析 持续更新

本篇主要针对在日常工作与学习中使用较多的linux指令的使用方法以及使用频次进行分析与讲解&#xff0c;旨在能够更好的掌握这些必备的技能。 linux指令非常的多&#xff0c;如果要记住所有的指令使用方法是非常困难的且要花费很长的时间&#xff0c;很多人习惯离开使用去通篇…...

Redis 字符串(String)

Redis 字符串(String) 介绍 Redis是一种开源的、高性能的键值数据库,它支持多种类型的数据结构,其中字符串(String)是Redis中最基本的数据类型之一。字符串类型可以存储任何形式的字符串,包括文本、序列化的对象或二进制数据。在Redis中,字符串类型的最大容量为512MB。 …...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...