c语言中联合Union的作用及示例代码说明

server/2024/11/14 1:44:05/

引言

在C语言中,联合(Union)是一种特殊的数据结构,它允许在相同的内存位置存储不同的数据类型。其它语言中没有类似的语法。
以下是联合的一些作用以及相应的例子。

作用

1 节省空间

联合可以用来节省内存,因为它允许多个成员共享同一块内存空间。例如,一个联合可以存储不同类型的数据,但任何时候只能使用其中一个。

union Data {int i;float f;char str[20];
};int main() {union Data data;data.i = 10; // 使用整数printf("%d\n", data.i);data.f = 220.5; // 使用浮点数printf("%f\n", data.f);strcpy(data.str, "C Programming"); // 使用字符串printf("%s\n", data.str);return 0;
}

数据共享

联合可以用来在不同的上下文中共享同一块内存区域。例如,一个联合可以用来存储一个整数或者一个浮点数,这取决于程序的需要。也是一种节省的情况。

union Number {int integer;float floating;
};int main() {union Number num;num.integer = 10;printf("Integer: %d\n", num.integer);num.floating = 220.5;printf("Float: %f\n", num.floating);return 0;
}

数据打包

在网络编程中,联合可以用来打包和解包数据。例如,一个联合可以用来存储一个IP地址的不同表示形式。

union IPAddr {struct { unsigned char byte1, byte2, byte3, byte4; } bytes;unsigned long addr;
};int main() {union IPAddr ipAddr;ipAddr.bytes.byte1 = 192;ipAddr.bytes.byte2 = 168;ipAddr.bytes.byte3 = 1;ipAddr.bytes.byte4 = 1;printf("IP Address: %lu\n", ipAddr.addr);return 0;
}

或如下函数:

//将BYTE字节组装成DWORD长字数据
DWORD MakeDword(BYTE by1, BYTE by2, BYTE by3, BYTE by4)
{Union{DWORD dwData;BYTE byData[4];}temp;temp.byData[0] = by1;temp.byData[1] = by2;temp.byData[2] = by3;temp.byData[3] = by4;return temp.dwData;
}

位域操作

联合可以与位域结合使用,以访问和操作单个位或位组。例如,一个联合可以用来存储一个结构体,该结构体包含位域。

union PackedData {struct {unsigned int a:1;unsigned int b:3;unsigned int c:4;} bits;unsigned int all;
};int main() {union PackedData data;data.bits.a = 1;data.bits.b = 7;data.bits.c = 15;printf("Packed Data: %u\n", data.all);return 0;
}

类型转换

联合可以用来实现不同数据类型之间的隐式类型转换。例如,一个联合可以用来存储一个字符数组或者一个整数。

union TypeCast {char str[4];int num;
};int main() {union TypeCast data;data.str[0] = 'C';data.str[1] = ' ';data.str[2] = 'P';data.str[3] = 'R';printf("String: %s\n", data.str);printf("Integer: %d\n", data.num);return 0;
}

内存对齐

联合可以用来绕过编译器的内存对齐规则。例如,一个联合可以用来存储一个结构体,该结构体的成员有不同的对齐要求。

union MemoryAlign {char c;double d;
};int main() {union MemoryAlign data;data.c = 'A';printf("Char: %c\n", data.c);data.d = 3.14;printf("Double: %f\n", data.d);return 0;
}

结构体成员

联合可以作为结构体的成员,这样可以在一个结构体中存储不同类型的数据。

struct Student {char name[50];union {int marks;float percentage;} scores;
};int main() {struct Student std;strcpy(std.name, "John Doe");std.scores.marks = 95;printf("Name: %s, Marks: %d\n", std.name, std.scores.marks);return 0;
}

变体类型

联合可以用来模拟变体类型,即可以存储多种类型中的一种。

union Variant {int i;float f;char *s;
};int main() {union Variant var;var.i = 10;printf("Integer: %d\n", var.i);var.f = 3.14f;printf("Float: %f\n", var.f);var.s = "Hello";printf("String: %s\n", var.s);return 0;
}

指针运算

联合的指针可以进行算术运算,因为联合的大小是其最大成员的大小。

union PointerArithmetic {int i;float f;
};int main() {union PointerArithmetic data;data.i = 10;printf("Integer: %d\n", data.i);// 指针运算printf("Next float: %f\n", *(float*)&data + 1.0f);return 0;
}

结论

使用联合union语法,能在程序中做出巧妙的设计,这也是c语言作为系统级语言独特的魅力之所在。
当然,在使用联合时,也需要确保正确地管理内存和数据类型,以避免潜在的错误和未定义行为。


http://www.ppmy.cn/server/141368.html

相关文章

关于Redis

Redis 基础 什么是 Redis? Redis (REmote DIctionary Server)是一个基于 C 语言开发的开源 NoSQL 数据库(BSD 许可)。与传统数据库不同的是,Redis 的数据是保存在内存中的(内存数据库&#xf…

原创:使用Qt Creator作为Linux IDE,实现CMake编译和gdb单步调试

1.前期简单步骤参考http://blog.csdn.net/libaineu2004/article/details/78448392 2.Linux下CMake简明教程 http://原文地址:https://blog.csdn.net/whahu1989/article/details/82078563 CMake是开源、跨平台的构建工具,可以让我们通过编写简单的配置…

如何在CentOS 7上搭建SMB服务

如何在CentOS 7上搭建SMB服务 因项目测试需求,需要自行搭建SMB服务,**SMB(Server Message Block)**协议是一种常用的文件共享方式,它可以让不同操作系统之间共享文件、打印机等资源。本文将带你一步步搭建一个简单的S…

Kafka-Eagle的配置——kafka可视化界面

通过百度网盘分享的文件:kafka-eagle-bin-2.0.8.tar.gz 链接:https://pan.baidu.com/s/1H3YONkL97uXbLTPMZHrfdg?pwdsltu 提取码:sltu 一、界面展示 二、软件配置 1、关闭kafka集群 kf.sh stop 2、将该软件上传到/opt/modules下 cd /opt…

MySQL 到 ClickHouse 数据同步优化(三)

简述 本文主要介绍 CloudCanal 如何将关系型数据库中数据同步到 ClickHouse,默认使用 ReplacingMergeTree 作为 ClickHouse 表引擎,链路特点包括: 新增 _version、_sign 字段,以便 ClickHouse 准确合并。DML 操作均以 INSERT 写…

esayExcel根据模板导出包含图片

1、效果 2、模板 3、工具类代码 /*** 根据模板填充* param response* param templateStream 模板文件流* param map 模板文件所需要的参数* param list list循环模板参数* throws IOException*/public static void templateFilling(HttpServletRequest servletRequest,HttpServ…

【Docker】自定义网络:实现容器之间通过域名相互通讯

文章目录 一. 默认网络:docker0网络的问题二. 自定义网络三. nginx容器指之间通过主机名进行内部通讯四. redis集群容器(跳过宿主机)内部网络通讯1. 集群描述2. 基于bitnami镜像的环境变量快速构建redis集群 一. 默认网络:docker0…

【QML 与 C++ 之间的通讯机制】QML 与 Qt 通讯:讲解如何在QML 中使用C++类,以及如何在C++ 中获取QML的内容

> 【QML 与 C 之间的通讯机制】QML 与 Qt 通讯:讲解如何在QML 中使用C类,以及如何在C 中获取QML的内容-阿里云开发者社区 在同一可执行文件中,C和QML共享同一个进程,但是它们运行在不同的线程上。 在Qt中,C和QML都是在同一个进程中运行的&…