You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将含联合体的C结构体转换为内存布局一致的C#结构体?

问题分析与解决方案

错误根源

你遇到的错误是因为C#中int[]是引用类型,它在结构体中存储的是指向托管数组对象的指针,而非数组的实际内存内容。CLR需要跟踪托管引用,不允许显式布局的结构体中出现引用类型字段与其他字段重叠,或引用类型字段之间重叠,因此抛出“偏移4处的对象字段对齐错误或被非对象字段重叠”的异常。

解决方案

方案1:使用unsafe固定数组(最贴合C语言内存布局,推荐)

该方案需要在项目属性中开启“允许unsafe代码”,直接对应C语言中数组的内存布局,结构体大小与C端完全一致。

// 对应C的s2结构体
public unsafe struct s2
{
    // 固定大小数组,直接在结构体内存中分配10个int的空间(40字节)
    public fixed int w[10];
}

// 对应C的s3结构体
public unsafe struct s3
{
    public fixed int w[10];
}

// 对应C的s1结构体(包含联合体)
[StructLayout(LayoutKind.Explicit)]
public unsafe struct s1
{
    [FieldOffset(0)]
    public int i;

    // 联合体成员共享偏移4开始的内存区域
    [FieldOffset(4)]
    public s2 u1;
    [FieldOffset(4)]
    public s3 u2;
}

方案2:非unsafe显式布局结构体(无需开启unsafe)

通过手动声明数组的每个元素,避免使用引用类型,让结构体成为纯值类型的 blittable 结构体:

[StructLayout(LayoutKind.Sequential)]
public struct s2
{
    // 手动声明10个int字段,对应C语言的int w[10]
    public int w0;
    public int w1;
    public int w2;
    public int w3;
    public int w4;
    public int w5;
    public int w6;
    public int w7;
    public int w8;
    public int w9;
}

[StructLayout(LayoutKind.Sequential)]
public struct s3
{
    public int w0;
    public int w1;
    public int w2;
    public int w3;
    public int w4;
    public int w5;
    public int w6;
    public int w7;
    public int w8;
    public int w9;
}

[StructLayout(LayoutKind.Explicit)]
public struct s1
{
    [FieldOffset(0)]
    public int i;

    [FieldOffset(4)]
    public s2 u1;
    [FieldOffset(4)]
    public s3 u2;
}

内容的提问来源于stack exchange,提问作者nuub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 12:40:23