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

如何获取嵌套结构体引用,递归计算带位域C#结构体等效C大小?

问题:递归计算带嵌套结构体与自定义位域的C#结构体等效C语言打包大小

我正在编写一个C#函数,用于计算某一C#结构体若以C语言打包结构体(__attribute__((packed)))实现时的大小。由于C#原生不支持位域,我通过自定义BitfieldLengthAttribute来模拟位域逻辑,因此无法直接使用Marshal.SizeOf(my_struct)。

结构体定义示例

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct struct_b{// 对应C语言:typedef struct __attribute__((packed)){    
    [BitfieldLength(1)]
    public byte flag_a;// uint8_t flag_a  :1;
    [BitfieldLength(1)]
    public byte flag_b;// uint8_t flag_b  :1;
    [BitfieldLength(2)]
    public byte flag_c;// uint8_t flag_c  :2;
    [BitfieldLength(1)]
    public byte flag_d;// uint8_t flag_d  :1;
    [BitfieldLength(3)]
    public byte reserved;// uint8_t reserved  :3;
    public float measure_1;//float measure_1
    public float measure_2;//float measure_2
    public UInt32 value_1; // uint32_t value_1;
}// struct_b;

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct struct_a{ 
    // 对应C语言:typedef struct __attribute__((packed)){
    public Int16 i_value_a;// int16_t i_value_a;
    public struct_b struct_field_b; //struct_b struct_field_b;
}// struct_a

现有实现与问题

我希望通过递归调用SizeInPackedBytes函数处理整个结构体,目前该函数能正确处理无嵌套的结构体,但无法处理包含嵌套结构体的场景。核心问题是:不知道如何从父结构体的FieldInfo中获取嵌套结构体的实例,以递归调用该函数。

现有函数的关键代码片段如下:

public static int SizeInPackedBytes(object structure, int i_start_idx, ref string str_parsed_struct){
    int i_bitset_counter = 0;
    int i_num_bits = 0;
    int i_byte_index = 0;
    int i_aux = 0;
    bool b_is_struct = false;
    int i_field_idx = 0;

    FieldInfo[] field_info_array = structure.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
    for (i_field_idx = 0; i_field_idx < field_info_array.Count(); i_field_idx++){
        FieldInfo field_info = field_info_array[i_field_idx];

        // 判断当前字段是否为嵌套结构体:结构体是ValueType,但不是基础类型或枚举
        b_is_struct = (field_info.FieldType.IsValueType && !field_info.FieldType.IsPrimitive && !field_info.FieldType.IsEnum);
        if (b_is_struct){
            // >>> 此处无法获取嵌套结构体实例,无法递归调用
            // 尝试过错误写法:object nested_struct = field_local.GetValue(null);
        }else{
            // 处理位域或普通字段的逻辑(已实现)
            // ...
        }
    }
    // ...
    return i_byte_index + (i_bitset_counter > 0 ? 1 : 0);
}

我需要正确实现从FieldInfo获取嵌套结构体实例的逻辑,替换上述代码中的注释部分。


解决方案

要获取父结构体中嵌套结构体的实例,需要调用FieldInfo.GetValue()并传入父结构体的实例(即函数参数structure),而不是null(null仅适用于静态字段)。修正后的嵌套结构体处理逻辑如下:

if (b_is_struct){
    // 1. 获取父结构体中当前嵌套结构体字段的实例
    object nestedStructInstance = field_info.GetValue(structure);
    // 2. 递归计算嵌套结构体的打包大小,传入当前的起始偏移和解析字符串引用
    int nestedSize = SizeInPackedBytes(nestedStructInstance, i_start_idx + i_byte_index, ref str_parsed_struct);
    // 3. 累加嵌套结构体的大小到总字节数
    i_byte_index += nestedSize;

    // 4. 处理位域对齐:嵌套结构体是完整的字节块,若之前有未填满的位域,需补全字节
    if (i_bitset_counter != 0){
        i_byte_index++;
        i_bitset_counter = 0;
    }
}

关键说明

  • GetValue(structure):因为嵌套结构体是父结构体的实例字段,必须传入父结构体的实例才能获取到对应的字段值,这是之前错误使用GetValue(null)的核心原因。
  • 递归调用:嵌套结构体本身可能包含位域或更深层次的嵌套,递归调用会自动处理这些场景。
  • 位域对齐:由于嵌套结构体是完整的字节单元,若之前有未填满的位域(i_bitset_counter != 0),需要先补全当前字节,再累加嵌套结构体的大小。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 11:43:09