铸造明确布局的结构 [英] Casting explicitly-laid out structures

查看:99
本文介绍了铸造明确布局的结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有这个结构,

[StructLayout(LayoutKind.Explicit)]
public struct Chapter4Time
{
    [FieldOffset(0)]
    public UInt16 Unused;
    [FieldOffset(2)]
    public UInt16 TimeHigh;
    [FieldOffset(4)]
    public UInt16 TimeLow;
    [FieldOffset(6)]
    public UInt16 MicroSeconds;
}

和此结构。

[StructLayout(LayoutKind.Explicit)]
public struct IEEE_1588Time
{
    [FieldOffset(0)]
    public UInt32 NanoSeconds;
    [FieldOffset(4)]
    public UInt32 Seconds;
}

如何将一个结构转换为另一个结构?

How would I convert from one structure to the other?

推荐答案

两个选项:

,但显式结构布局

(请注意,尽管对于C#编译器来说这并不是不安全的,但有些框架可能仍然禁止它 - )

(Note that although this isn't unsafe as far as the C# compiler is concerned, some frameworks may still disallow it - see Marc Gravell's comment.)

您可以使用联合类型,它只是另一个具有两个字段的结构,两个字段都明确设置到同一个位置。下面是使用你的结构的一个完整的例子:

You could use a union type, which is just another struct with two fields, both set explicitly to the same location. Here's a complete example using your structures:

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Explicit)]
public struct Chapter4Time
{
    [FieldOffset(0)]
    public UInt16 Unused;
    [FieldOffset(2)]
    public UInt16 TimeHigh;
    [FieldOffset(4)]
    public UInt16 TimeLow;
    [FieldOffset(6)]
    public UInt16 MicroSeconds;
}

[StructLayout(LayoutKind.Explicit)]
public struct IEEE_1588Time
{
    [FieldOffset(0)]
    public UInt32 NanoSeconds;
    [FieldOffset(4)]
    public UInt32 Seconds;
}

[StructLayout(LayoutKind.Explicit)]
public struct TimeUnion
{
    [FieldOffset(0)]
    public Chapter4Time Chapter4Time;
    [FieldOffset(0)]
    public IEEE_1588Time IEEE_1588Time;
}

class Test
{    
    static void Main()
    {
        var ch4 = new Chapter4Time { TimeLow = 100, MicroSeconds = 50 };
        var union = new TimeUnion { Chapter4Time = ch4 };
        Console.WriteLine(union.IEEE_1588Time.Seconds);
    }
}

不安全的代码,投放指针

如果你可以使用不安全的代码,一个替代union类型的方法是转换 Chapter4Time * IEEE_1588Time *

An alternative to the union type if you can use unsafe code is to cast a pointer of type Chapter4Time* to IEEE_1588Time*:

class Test
{    
    unsafe static void Main()
    {
        var ch4 = new Chapter4Time { TimeLow = 100, MicroSeconds = 50 };
        var ieee1588 = *((IEEE_1588Time*) &ch4);
        Console.WriteLine(ieee1588.Seconds);
    }
}

我个人如果所有可能的,但如果你真的,真的想做,这可能是最简单的方法。

Personally I'd avoid doing any of this if at all possible, but if you *really, really want to do it, these are probably the simplest approaches.

这篇关于铸造明确布局的结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆