将C#raw缓冲区重新解释为一个可跳转的结构

将C#raw缓冲区重新解释为一个可跳转的结构,c#,pointers,unsafe,reinterpret-cast,stackalloc,C#,Pointers,Unsafe,Reinterpret Cast,Stackalloc,我正在寻找一种方法,将任意不安全内存区域重新解释为C#中的可blittable结构。以下是迄今为止我可以写的一个失败的尝试: [StructLayout(LayoutKind.Explicit, Size = sizeof(int))] struct Foo { [FieldOffset(0)] public int X; } public static unsafe void Main() { // Allocate the buffer byte* buff

我正在寻找一种方法,将任意不安全内存区域重新解释为C#中的可blittable结构。以下是迄今为止我可以写的一个失败的尝试:

[StructLayout(LayoutKind.Explicit, Size = sizeof(int))]
struct Foo
{
    [FieldOffset(0)]
    public int X;
}

public static unsafe void Main()
{
    // Allocate the buffer
    byte* buffer = stackalloc byte[sizeof(Foo)];

    // A tentative of reinterpreting the buffer as the struct
    Foo foo1 = Unsafe.AsRef<Foo>(buffer);

    // Another tentative to reinterpret as the struct
    Foo foo2 = *(Foo*) buffer;

    // Get back the address of the struct
    void* p1 = &foo1;
    void* p2 = &foo2;

    Console.WriteLine(new IntPtr(buffer).ToString("X"));
    Console.WriteLine(new IntPtr(p1).ToString("X"));
    Console.WriteLine(new IntPtr(p2).ToString("X"));
}
[StructLayout(LayoutKind.Explicit,Size=sizeof(int))]
结构Foo
{
[字段偏移量(0)]
公共int X;
}
公共静态不安全void Main()
{
//分配缓冲区
字节*buffer=stackalloc字节[sizeof(Foo)];
//将缓冲区重新解释为结构的尝试
Foo foo1=不安全的.AsRef(缓冲区);
//重新解释为结构的另一个尝试
Foo-foo2=*(Foo*)缓冲区;
//获取结构的地址
void*p1=&foo1;
void*p2=&foo2;
Console.WriteLine(新的IntPtr(buffer.ToString)(“X”);
Console.WriteLine(新的IntPtr(p1.ToString)(“X”);
Console.WriteLine(新的IntPtr(p2).ToString(“X”);
}
然而,打印的内存地址都是不同的(我希望打印相同的地址)。第一次尝试使用Microsoft提供的
Unsafe.AsRef(..)
,其中方法说明如下:

将给定位置重新解释为对类型为
T
的值的引用

我不知道为什么这里没有正确地进行重新解释


有什么建议吗?

重新解释工作正常,地址不同的原因是这两行在两个新变量中创建了独立的数据副本:

Foo foo1 = Unsafe.AsRef<Foo>(buffer);
// ...
Foo foo2 = *(Foo*) buffer;

嘿@kalimag,谢谢你的回答!这是否意味着我的触角实际上是在复制内存中的结构,而不是引用缓冲区?您使用
ref
局部变量的示例非常好。为了完整起见,请您添加第二个不使用
ref
局部变量的代码段,因为我不确定您的意思,但随后您取消引用
ref Foo/Foo*
,并将它们分配给
foo1
foo2
?如果没有
ref
locals技巧,我不知道如何解决这个问题。非常感谢!是的,每当您为新变量指定
结构时,都会复制该值。如果要避免该复制,需要使用
ref Foo
Foo*
引用原始内存位置,而不要将其分配给
Foo
类型的新变量。我不确定你到底想解决什么问题,但如果你想坚持使用指针,你所需要的就是像
Foo*Foo=(Foo*)buffer这样的代码;foo->X=123没错!这充分回答了我的问题。非常感谢!
byte* buffer = ...

// Option 1, pointers only
Foo* foo1 = (Foo*)buffer;
foo1->X = 123;

// Option 2, ref local cast from pointer    
ref Foo foo2 = ref *(Foo*)buffer;
foo2.X = 456;

// Option 3, ref local with Unsafe.AsRef
// Unlike option 2 this also allows reinterpreting non-blittable types,
// but in most cases that's probably undesirable
ref Foo foo3 = ref Unsafe.AsRef<Foo>(buffer);
foo3.X = 789;