iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >怎么在c#中利用结构体实现共用体
  • 567
分享到

怎么在c#中利用结构体实现共用体

2023-06-14 11:06:36 567人浏览 泡泡鱼
摘要

怎么在C#中利用结构体实现共用体?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。理解 C 语言的共用体在 C 语言中,共用体是一种特殊的数据类型,允许你使用相同的一段内存空间存储

怎么在C#中利用结构体实现共用体?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

理解 C 语言的共用体

在 C 语言中,共用体是一种特殊的数据类型,允许你使用相同的一段内存空间存储不同的成员数据。光看定义有点抽象,我们来看一个 C 语言的共用体示例:

#include <stdio.h>uNIOn data{    int n;    char ch;    short m;};int main(){    union data a;    printf("%d, %d\n", sizeof(a), sizeof(union data) );    a.n = 0x40;    printf("%X, %c, %hX\n", a.n, a.ch, a.m);    a.ch = '9';    printf("%X, %c, %hX\n", a.n, a.ch, a.m);    a.m = 0x2059;    printf("%X, %c, %hX\n", a.n, a.ch, a.m);    a.n = 0x3E25AD54;    printf("%X, %c, %hX\n", a.n, a.ch, a.m);    return 0;}

运行结果:

4, 4
40, @, 40
39, 9, 39
2059, Y, 2059
3E25AD54, T, AD54

要想理解上面的输出结果,就得了解共用体各个成员在内存中的分布。此示例中的 data 各个成员在内存中的分布示意图如下:

怎么在c#中利用结构体实现共用体

也就是说共用体的所有成员占用的是同一段内存,所占内存等于最长的成员占用的内存,修改一个成员会影响其它所有成员。而结构体的各个成员占用的是各自不同的内存,所占内存大于等于所有成员占用的内存的总和(成员之间可能会存在缝隙),成员相互之间没有影响。这是共用体和结构的主要区别。

使用 C# 实现共用体

和 C 语言不同的是,C# 中没有共用体的定义。那在 C# 中如何来实现这种定义呢?

C# 不仅可以实现共用体,而且可以实现比 C 语言更强大的共用体。C 语言的共用体每个成员在共用的内存中都必须从相同的起始位置开始存储,而在 C# 中可以指定各成员的起始位置(相对偏移)。好处是,不仅可以节省内存空间,还可以实现一些自动转换操作。

以 IP 地址的存储为例,IP 地址是以 4 段数字来表示的(如 192.168.1.10),每一段是一个字节(Byte),长度是 2^8,最大值是 255。我们可以用很多类型来表示 IP 地址,比如字符串、整型、自定义类和结构等。但如果我们有时要访问或修改其中一段,怎样存储最为方便呢?

我们可以使用 C# 的显示布局结构体来实现类似 C 语言中的共用体,以方便灵活地操作 IP 地址的每一段。实现方式如下:

using System.Runtime.InteropServices;[StructLayout(LayoutKind.Explicit)]public struct IpAddress{    // FieldOffset 表示偏移的位置(以字节为单位)    // sizeof(int) = 4, sizeof(byte) = 1    [FieldOffset(0)] public int Address;    [FieldOffset(0)] public byte Byte1;    [FieldOffset(1)] public byte Byte2;    [FieldOffset(2)] public byte Byte3;    [FieldOffset(3)] public byte Byte4;    public IpAddress(int address) : this()    {        // 给 Address 赋值时,所有成员的值都会自动被修改        Address = address;    }    public override string ToString() => $"{Byte1}.{Byte2}.{Byte3}.{Byte4}";}

这里我们使用了 StructLayout 特性标注了 IpAddress,声明其内存分布是显示(Explicit)的,然后使用 FieldOffset 特性来标注成员在共用内存中相对起始位置的偏移量(以字节为单位)。

如此我们就用 C# 实现了和 C 语言一样的共用体。可能你不能马上体会这样实现的妙处,让来我们来看一个应用场景。

假设我要在 IP 段内随机生成一个 IP,比如前两段不变,后两段随机,形如:192.163.X.X。使用上面定义好的“共用体”,我们可以这样做:

var ip = new IpAddress(new Random().Next());Console.WriteLine($"{ip} = {ip.Address}");ip.Byte1 = 192;ip.Byte2 = 168;Console.WriteLine($"{ip} = {ip.Address}");

输出结果:

29.249.122 = 2063146287
192.168.249.122 = 2063182016

这样不仅节省内存,而且可以很灵活方便地读取和修改 IP 中的某一段。由于成员 Address 和其它成员共用内存,所以修改一个成员,其余就自动修改。

共用体作为另一个共用体的成员

既然“共用体”是值类型,那么共用体自然也可以作为作为另一个共用体的成员。让我们来看一个较为复杂的例子,使用共用体实现由协议、IP 和端口三部分组成的服务端地址的表示,形如:协议://IP:端口。

using System;using System.Runtime.InteropServices;[StructLayout(LayoutKind.Explicit)]public struct IpAddress{    [FieldOffset(0)] public int Address;    [FieldOffset(0)] public byte Byte1;    [FieldOffset(1)] public byte Byte2;    [FieldOffset(2)] public byte Byte3;    [FieldOffset(3)] public byte Byte4;    public IpAddress(int address) : this()    {        Address = address;    }    public override string ToString() => $"{Byte1}.{Byte2}.{Byte3}.{Byte4}";}public enum Protocol : byte { Httphttps, ftp, sftp, tcp };[StructLayout(LayoutKind.Explicit)]public struct Server{    [FieldOffset(0)] public IpAddress Address;    [FieldOffset(4)] public ushort Port;    [FieldOffset(6)] public Protocol Protocol;    [FieldOffset(0)] public long Payload;    public Server(IpAddress addr, ushort port, Protocol prot) : this()    {        Address = addr;        Port = port;        Protocol = prot;    }    public Server(long payload)    {        // 参数长度可能不足填满每个成员,所以这里先对成员设初始值        Address = new IpAddress(0);        Port = 80;        Protocol = Protocol.http;        // 填值        Payload = payload;    }    public Server Copy() =>  new Server(Payload);    public override string ToString() => $"{Protocol}://{Address}:{Port}";}

我们来用一段测试代码验证一下这个Server结构体的内存使用情况:

var ip = new IpAddress(new Random().Next());Console.WriteLine($"Size: {Marshal.SizeOf(ip)} bytes. Value: {ip.Address} = {ip}");var s1 = new Server(ip, 8080, Protocol.https);var s2 = new Server(s1.Payload);s2.Address.Byte1 = 100;s2.Protocol = Protocol.ftp;Console.WriteLine($"Size: {Marshal.SizeOf(s1)} bytes. Value: {s1.Address} = {s1}");Console.WriteLine($"Size: {Marshal.SizeOf(s2)} bytes. Value: {s2.Address} = {s2}");

输出结果:

Size: 4 bytes. Value: 2102736192 = 64.53.85.125
Size: 8 bytes. Value: 64.53.85.125 = https://64.53.85.125:8080
Size: 8 bytes. Value: 100.53.85.125 = ftp://100.53.85.125:8080

看完上述内容,你们掌握怎么在c#中利用结构体实现共用体的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注编程网精选频道,感谢各位的阅读!

--结束END--

本文标题: 怎么在c#中利用结构体实现共用体

本文链接: https://www.lsjlt.com/news/270557.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么在c#中利用结构体实现共用体
    怎么在c#中利用结构体实现共用体?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。理解 C 语言的共用体在 C 语言中,共用体是一种特殊的数据类型,允许你使用相同的一段内存空间存储...
    99+
    2023-06-14
  • c# 如何使用结构体实现共用体
    目录理解 C 语言的共用体使用 C# 实现共用体共用体作为另一个共用体的成员在 C 和 C# 编程语言中,结构体(Struct)是值类型数据结构,它使得一个单一变量可以存储多种类型的...
    99+
    2024-04-02
  • C语言中的结构体和共用体怎么使用
    这篇文章主要介绍了C语言中的结构体和共用体怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言中的结构体和共用体怎么使用文章都会有所收获,下面我们一起来看看吧。结构体 / struct结构体的定义声明一...
    99+
    2023-06-16
  • C语言中结构体和共用体实例教程
    目录一、实验目的二、实验内容三、实验记录3.1 候选人选票统计3.2 print函数3.3 链表总结一、实验目的 掌握结构体类型变量的定义和使用; 掌握结构体类型...
    99+
    2024-04-02
  • C语言中结构体和共用体如何使用
    本篇文章给大家分享的是有关C语言中结构体和共用体如何使用,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。结构体 / struct结构体的定义声明一个结构体类型的一般形式为:str...
    99+
    2023-06-16
  • c++中结构体怎么用
    结构体是一种复合数据类型,可组合不同类型的数据。创建结构体:使用 struct 关键字,定义成员的类型和名称。访问成员:使用点运算符 (.) 访问成员变量。使用结构体指针:使用结构体指针...
    99+
    2024-05-12
    c++
  • 解析C/C++指针、函数、结构体、共用体
    目录指针变量与地址指针与指针变量占内存空间指针运算指针 变量与地址 变量给谁用的变量是对某一块空间的抽象命名。变量名就是你抽象出来的某块空间的别名。指针就是地址。指向某个地址。 指针...
    99+
    2024-04-02
  • C++结构体字节对齐和共用体大小
    目录1、结构体内存对齐2、共用体的内存大小3、枚举的大小1、结构体内存对齐 结构体内存对齐在笔试和面试中经常被问到,所以做个总结 通过代码验证不同结构体的内存大小: #inclu...
    99+
    2024-04-02
  • C语言中结构体和共用体的示例分析
    这篇文章给大家分享的是有关C语言中结构体和共用体的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、实验目的掌握结构体类型变量的定义和使用;掌握结构体类型数组的概念和应用;掌握链表的概念,初步学会对链表进...
    99+
    2023-06-20
  • C#结构体怎么使用
    本篇内容介绍了“C#结构体怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!实例using System;using ...
    99+
    2023-06-17
  • C#的结构体怎么用
    小编给大家分享一下C#的结构体怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!C#的结构体使用程序:public struct conte...
    99+
    2023-06-18
  • 如何分析C/C++指针、函数、结构体和共用体
    如何分析C/C++指针、函数、结构体和共用体,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。指针变量与地址变量给谁用的变量是对某一块空间的抽象命名。变量名就是你抽象出来的某块...
    99+
    2023-06-28
  • C++ Struct结构体怎么使用
    今天小编给大家分享一下C++ Struct结构体怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一.C语言 ...
    99+
    2023-07-05
  • C++的结构体struct怎么用
    这篇文章主要讲解了“C++的结构体struct怎么用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++的结构体struct怎么用”吧!struct 结构体占用空间在C++ 中空结构体占1个...
    99+
    2023-06-29
  • c语言结构体怎么用
    非常抱歉,由于您没有提供文章标题,我无法为您生成一篇高质量的文章。请您提供文章标题,我将尽快为您生成一篇优质的文章。...
    99+
    2024-05-15
  • C#中如何使用结构体
    这期内容当中小编将会给大家带来有关C#中如何使用结构体,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。例如C++中定义的以下结构体:struct RCEStruct { &nb...
    99+
    2023-06-18
  • C语言中的结构体怎么使用
    这篇文章主要讲解了“C语言中的结构体怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C语言中的结构体怎么使用”吧!一、关于结构体在C语言中,结构体(struct)指的是一种数据结构,是...
    99+
    2023-06-16
  • C++中如何使用结构体
    这篇文章给大家介绍C++中如何使用结构体,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构。建议大家可以和这篇文章结合着来看,C++的中的...
    99+
    2023-06-17
  • Linux的file结构体和inode结构体怎么用
    本篇内容介绍了“Linux的file结构体和inode结构体怎么用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. file 结构体fil...
    99+
    2023-06-27
  • C语言中的结构体在Python中实现转换
    目录struct介绍struct中的常用接口pack()unpack()fmt示例struct介绍 Python中提供了struct接口,用来处理类似C语言中的结构体。 处理的方式是...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作