当前位置: 首页 > 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语言的基础,高效利用这些特性将有助于解决实际编程中的复杂问题。

http://www.lryc.cn/news/373547.html

相关文章:

  • React Hooks小记(三)_forwardRef
  • 面试复习记录
  • 块级元素与行内元素详解
  • Kotlin编程实践-【Java如何调用Kotlin中带默认值参数的函数】
  • 中国城市统计年鉴(1985-2023年)
  • RestTemplate远程请求的艺术
  • Spring 整合 MyBatis 底层源码解析
  • LeetCode 189.轮转数组
  • JDK17 你的下一个白月光
  • springboot优雅shutdown时如何保障异步线程的安全
  • C++格式化库fmt使用方法
  • HTML 颜色名:网页设计的调色板
  • 12306 火车票价格解析 (PHP 解析)
  • 了解统计学中不同类型的分布
  • k8s-CCE创建工作负载变量引用
  • 后端主流框架--Spring02
  • [数据集][目标检测]减速带检测数据集VOC+YOLO格式5400张1类别
  • 分析Linux操作指令及使用场景与频率分析 持续更新
  • Redis 字符串(String)
  • 第一篇:容器化的未来:从Docker的革命到云原生架构
  • 【2024最新华为OD-C/D卷试题汇总】[支持在线评测] URL拼接(100分) - 三语言AC题解(Python/Java/Cpp)
  • 反射,枚举以及lambda表达式
  • DNS域名解析----分离解析、多域名解析、父域与子域
  • Spring底层架构核心概念解析
  • C++ 44 之 指针运算符的重载
  • onlyoffice在线预览加载优化
  • 依赖自动装配
  • mysql和redis的双写一致性问题
  • Qwen2——阿里巴巴最新的多语言模型挑战 Llama 3 等 SOTA
  • 等级考试3-2021年3月题