当前位置: 首页 > 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。 …...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...