C#借助FieldOffset属性实现共用体与强制类型转换
2015-12-07 20:37
405 查看
C#上还是新手,突然就接触到属性是不是有点超前了呢。先Mark下来。如果对于文章中的问题有更好的解决办法请告诉我。
C#借助FieldOffset属性实现共用体与强制类型转换
这两天被C#的强制类型转换弄得有点不习惯。事出如此。
在C#中,我打算读二进制文。文件的结构很简单,一连串的紧密存储的int32值,以二进制方式存放。现在我希望随机读取第n个int32开始的i个值,并读入到数组中。结果查一下C#只能读到byte[]中,要不就是一个个读出来循环放int[]。追求效率的我当然不希望这样,如果能像C++那样将byte[]强制转换成int[]就好了。例如:
在C#中无法直接实现,为此我想了好些办法,也查了好久,直到我见到了这样的代码:
原理实际上跟C++一样,将一个int[]型的变量指向与byte[]型变量相同的内存区域,跟C++中将dat指向char数组的首地址是一样的。同样,这样的结构体功能与C++的共用体是一样的,即一个结构可以作为多种数据类型,而具体是什么类型视情况而定。
测试所使用的文件就不上传了,有WinHex的可以自己编辑一个,没有的也可以写程序将从0xF到0x0的16个数以二进制方式输出到文件中。文件的内容用WinHex打开以16进制显示应该如下:
C#借助FieldOffset属性实现共用体与强制类型转换
这两天被C#的强制类型转换弄得有点不习惯。事出如此。
在C#中,我打算读二进制文。文件的结构很简单,一连串的紧密存储的int32值,以二进制方式存放。现在我希望随机读取第n个int32开始的i个值,并读入到数组中。结果查一下C#只能读到byte[]中,要不就是一个个读出来循环放int[]。追求效率的我当然不希望这样,如果能像C++那样将byte[]强制转换成int[]就好了。例如:
char tmp[64]; // 16个int。相当于C#的 byte[] tmp = new int[64]; int* dat; // dat的指针。相当于C#的 int[] dat; ifstream IF(...); // 标准文件输入流。相当于C#的 FileStream FS = new FileStream(...); IF.read(tmp, 64); // 读取64个字节。 相当于C#的 FS.Read(tmp,0,64); dat = (int*)tmp; // 将tmp数组的首地址转为int类型,则数组以4个字节为一个int转换为int型的数组。 // 数据在内存上没有任何变化,因为数据本来就是int型的。 // 关键是这一步在C#中无法直接实现。 for (int i = 0; i < 16; i++) cout << dat[i] << " "; // 输出数据。相当于C#的 Console.Write(dat[i]+" ");
在C#中无法直接实现,为此我想了好些办法,也查了好久,直到我见到了这样的代码:
using System; using System.IO; using System.Collections.Generic; using System.Linq; using System.Text; // 提供各种各样支持 COM 互操作 及平台调用服务的成员 using System.Runtime.InteropServices; namespace test { class Program { // StructLayout使设计者可以控制类或结构的数据字段的物理布局 // Explicit与FieldOffset一起可以控制每个数据成员的精确位置 [StructLayout(LayoutKind.Explicit)] public struct S1 { // FieldOffset控制字段所在的物理位置偏移为0 [FieldOffset(0)] public byte[] a; // 同样偏移为0,开始位置与a重叠了。 [FieldOffset(0)] public int[] b; } static void Main(string[] args) { S1 s = new S1(); // 要new,不然b会报“使用了可能未赋值的字段” s.a=new byte[64]; FileStream FS = new FileStream("E:\\test.txt", FileMode.Open); // 以s.a来接收文件的数据 FS.Read(s.a,0,64); // 自己保证读b的时候不要越界 for (int i = 0; i < 16; i++) Console.Write(s.b[i]+" "); // 以b来使用数据 Console.ReadKey(); } } }
原理实际上跟C++一样,将一个int[]型的变量指向与byte[]型变量相同的内存区域,跟C++中将dat指向char数组的首地址是一样的。同样,这样的结构体功能与C++的共用体是一样的,即一个结构可以作为多种数据类型,而具体是什么类型视情况而定。
测试所使用的文件就不上传了,有WinHex的可以自己编辑一个,没有的也可以写程序将从0xF到0x0的16个数以二进制方式输出到文件中。文件的内容用WinHex打开以16进制显示应该如下:
相关文章推荐
- C#邮件发送
- C#操作XML的方法
- c#通用递归生成无限层级树
- C#特性详解
- 造轮子:C#中将图片转化成base64字符串
- c#获取当前月的第一天和最后一天
- C# Mvc中文件下载
- C#遍历类的属性 PropertyInfo.Attributes
- c# 动态操作 zip\rar 文件,压缩解压组件使用
- c#如何将winform窗体封装成可以引用的dll文件
- C#使用事务
- C#邮箱发送验证码
- C#实现简单聊天程序的方法
- C#邮箱发送
- C#类型转换总结(三)各类型转化实例
- C# 八进制数值字符串转换成ASCII 字符串相互转换
- C# 操作自定义config文件
- c#生成时间戳
- C# 函数中的out型参数
- C#模拟windows账户登录,并复制文件代码