C#联合Union的实现方式
一.基础篇
C#不像C++,他本身是没有联合Union的,但是可以通过手动控制结构体每个元素的位置来实现,这需要结合使用StructLayoutAttribute、LayoutKind以及FieldOffsetAttribute。使用它们的时候必须引用System.Runtime.InteropServices下面是我写的模拟U的联合。
[StructLayout(LayoutKind.Explicit, Size = )]
struct U
{
[FieldOffset()]
public byte b0;
[FieldOffset()]
public byte b1;
[FieldOffset()]
public byte b2;
[FieldOffset()]
public byte b3; [FieldOffset()]
public int i; [FieldOffset()]
public float f;
}
我们知道联合中每个数据成员都在相同的内存地址开始,所以我们要通过[FieldOffset(0)]应用到U的每一个成员,意思就是让这些成员处于同一个开始位置。当然,我们得事先告诉.NET这些成员的内存布局由我们来作主,所以要使用LayoutKind.Explicit枚举然后传递给StructLayoutAttribute,并应用到U上,这样.Net就不会再干涉该struct的成员在内存中的布局了。并且我定义了U的Size为12,当然你也可以不定义U的Size。
而且使用联合进行数据转换比BitConverter要快。测试用例如下:
{
DateTime past = DateTime.Now;
int length = * * ;
for (int i = ; i < length; i++)
{
U a = new U();
a.b0 = 0xFF;
a.b1 = 0xFF;
int res = a.i;
}
DateTime now = DateTime.Now;
Console.WriteLine((now - past));
}
{
DateTime past = DateTime.Now;
int length = * * ;
for (int i = ; i < length; i++)
{
byte[] a = { 0xFF, 0x0F, 0x0F, };
object b = a;
int res = BitConverter.ToInt32(a, );
}
DateTime now = DateTime.Now;
Console.WriteLine((now - past));
}
二.进阶篇
之前的方法还存在好多问题,比如数组没法放入联合中,会提示值和引用冲突什么的。
今天又研究了一下,利用C#中可以使用指针的特性,结合unsafe和fixed,实现数组类型和普通值类型的共存。
方法① 数组类型和普通值类型的共存——固定大小的缓冲区
利用固定大小的缓冲区(fixed)实现数组类型和普通值类型的共存
[StructLayoutAttribute(LayoutKind.Explicit, Pack = )]
public unsafe struct A
{
[FieldOffset()]
public int a;
[FieldOffset()]
public byte b;
[FieldOffset()]
public float c;
[FieldOffset()]
public fixed byte arr[];
};
方法② 结构体转字节数组——1).使用联合 2).使用指针强制转换
1).使用联合,利用一个和原结构体等长的fixed byte buff[n],这个buff就是我们要的直接数组,访问时需要通过fixed (byte* ta = a.buff) {}来访问。
[StructLayoutAttribute(LayoutKind.Explicit, Pack = )]
public unsafe struct A
{
[FieldOffset()]
public int a;
[FieldOffset()]
public byte b;
[FieldOffset()]
public float c;
[FieldOffset()]
public fixed byte buff[];
};
2).直接使用指针强制转换,通过fixed,先将结构体转换为void *,再将其转化为byte* b。
fixed (void * ta = &a)
{
byte* b = (byte*)ta ;
}
3).最后通过IntPtr拷贝到C#标准的byte[]中。
byte[] Dbuff = new byte[];
IntPtr pstart = new IntPtr(a);
Marshal.Copy(pstart, Dbuff, , );
C#联合Union的实现方式的更多相关文章
- 结构体struct 与 联合union
1.C语言中的结构体 1.1 定义 结构体是由一系列相同或不同类型的变量组成的集合. struct 结构体名{ //struct为关键字,“结构体名”为用户定义的类型标识. ...
- 【转】结构struct 联合Union和枚举Enum的细节讨论
结构struct 联合Union和枚举Enum的细节讨论 联合(Union)是一种构造数据类型,它提供了一种使不同类型数据类型成员之间共享存储空间的方法,同时可以实现不同类型数据成员之间的自动类型转换 ...
- c++ 变量共享内存-联合(union)
共享内存极少使用,所以这里我们仅作了解. .将几个变量放在相同的内存区,但其中只有一个变量在给定时刻有有效值. .程序处理许多不同类型的数据,但是一次只处理一种.要处理的类型在执行期间才能确定. .在 ...
- SQL SERVER 2012 第四章 连接 JOIN语句的早期语法结构 & 联合UNION
1/内部连接的早期语法结构 INNER JOIN SELECT * FROM Person.Person JOIN HumanResources.Employee ON Person.Person.I ...
- C语言学习015:联合(union)与枚举(enum)
联合 联合和结构的区别是,结构会为每个字段申请一片内存空间,而联合只是申请了一片内存空间然后所有字段都会保存到这片空间中,这片空间的大小由字段中最长的决定,下面我们就开始定义一个联合 //联合的定义 ...
- C 语言 联合union初见
1.什么是联合? “联合”是一种构造类型的数据结构.在一个“联合”内可以定义多种不同的数据类型, 一个被说明为该“联合”类型的变量中,允许装入该“联合”所定义的任何一种数据,这些数据共享同一段内存,已 ...
- 结构struct 联合Union和枚举Enum的细节讨论
联合(Union)是一种构造数据类型,它提供了一种使不同类型数据类型成员之间共享存储空间的方法,同时可以实现不同类型数据成员之间的自动类型转换.联合体对象在同一时间只能存储一个成员的值.联合的内存大小 ...
- c语言联合union的使用用途
在使用联合的使用,我们通常用来判断大小端,但是其实不仅仅有这个用处. 我在网上看到还有其他的用途: 1.分离高低字节 这个需要结合cpu大小端来判断,原文如下: 这样的操作,而一个除法消耗四个机器周期 ...
- hibernate联合主键 注解方式
转载自https://my.oschina.net/yotoo/blog/265571 方法一:主键类用@Embeddable,pojo类仍然用@Entity但是引用主键类的对象用@Id 主键pojo ...
随机推荐
- C#编写简单的聊天程序
这是一篇基于Socket进行网络编程的入门文章,我对于网络编程的学习并不够深入,这篇文章是对于自己知识的一个巩固,同时希望能为初学的朋友提供一点参考.文章大体分为四个部分:程序的分析与设计.C#网络编 ...
- 深入了解ibatis源码----简单ibatis示例代码
搭建源码环境: 1.创建sql数据库. CREATE TABLE USER_ACCOUNT ( USERID INT(3) NOT NULL AUTO_INCREMENT, USERNAME VARC ...
- 报告一个IE很奇葩的滚动条问题——百分比计算宽度为浮点数时的滚动条显示异常
起因: 做项目的时候做了一个表格内容超过DIV容器自动横向滚动处理.别的浏览器都正常:但是在IE下面明明表格table和容器DIV宽度一致但是却出现了滚动条.如图 然后本人做实验找了半天原因终于是找到 ...
- 基于HTML5的WebGL电信网管3D机房监控应用
先上段视频,不是在玩游戏哦,是规规矩矩的电信网管企业应用,嗯,全键盘的漫游3D机房: http://www.hightopo.com/guide/guide/core/3d/examples/exam ...
- 基于MVC4+EasyUI的Web开发框架经验总结(1)-利用jQuery Tags Input 插件显示选择记录
最近花了不少时间在重构和进一步提炼我的Web开发框架上,力求在用户体验和界面设计方面,和Winform开发框架保持一致,而在Web上,我主要采用EasyUI的前端界面处理技术,走MVC的技术路线,在重 ...
- Apache+PHP 配置随笔
准备安装包 1:安装VC++ 2012(vcredist_x64,我这边服务器为64位) 2:Apache安装包,php安装包 安装后配置工作 1:安装Apache服务,配置环境变量 httpd -k ...
- MySQL建表规范与常见问题
一. 表设计 库名.表名.字段名必须使用小写字母,“_”分割. 库名.表名.字段名必须不超过12个字符. 库名.表名.字段名见名知意,建议使用名词而不是动词. 建议使用InnoDB存储引擎. 存储精确 ...
- [教学] 将 Form 内的控件变成 Style 简易运用
1. 在 Form 上放一个 TImage ,再一个 TText 到 Image 里面,并将 Image1.StyleName 设定为 BtnStyle,如下: 2.接着放一个 TButton,将 S ...
- 完善ext.grid.panel中的查询功能(紧接上一篇)
今天的代码主要是实现,Ext.grid.panel中的查询,其实我也是一名extjs新手,开始想的实现方式是另外再创建一个新的grid类来存放查询出的数据(就是有几个分类查询就创建几个grid类),这 ...
- eclipse新建maven项目(2)
本篇博文是继续之前的博文eclipse新建maven项目(1),那篇博文不在随笔在文章中.首先按照之前那篇博文进行创建maven项目操作,一系列操作下来之后发现刷新项目后会报错: 别急哈,可以解决. ...