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

ARM Cortex-A72平台下自引用宏的终止条件实现与递归代码生成器问题

ARM Cortex-A72平台下自引用宏的终止条件实现与递归代码生成器问题

我来帮你解决这个递归宏的棘手问题!首先得明确你遇到的核心卡点:C预处理器有个硬性规则——宏展开时如果直接引用自身,会被标记为「已展开过」,不会再触发递归调用,所以你之前直接在CHILD宏里写CHILD(pName,__VA_ARGS__)是完全无效的。

要绕开这个限制,我们可以把递归逻辑拆分成终止宏、递归处理宏、分发宏三部分,用两层宏间接调用的方式规避自引用问题,同时通过参数数量自动判断终止时机,完全不需要依赖带固定迭代次数的FOR_EACH宏。下面是具体的可运行实现方案:

完整代码实现

#include <cstdint>

// 1. 递归终止宏:当没有剩余参数时触发,什么都不做
#define CHILD_REC_END()

// 2. 递归处理核心:每次处理一个子项的参数,然后间接触发递归处理剩余参数
#define CHILD_REC_HELPER(pName, cName, start, N, ...) \
    struct cName##_t { \
        int test; \
    }; \
    cName##_t cName; \
    CHILD_REC(pName, __VA_ARGS__)  // 间接递归,通过CHILD_REC触发而非直接调用自身

// 3. 分发宏:根据剩余参数数量选择继续递归还是终止
//    原理:如果剩余参数>=3个(对应一个子项的cName/start/N),就选CHILD_REC_HELPER;否则选CHILD_REC_END
#define _CHILD_REC_DISPATCH(_1, _2, _3, MACRO, ...) MACRO

// 4. 对外暴露的递归入口宏:间接调用分发宏,绕开自引用限制
#define CHILD_REC(pName, ...) \
    _CHILD_REC_DISPATCH(__VA_ARGS__, CHILD_REC_HELPER, CHILD_REC_END)(pName, __VA_ARGS__)

// 5. 父类定义宏:调用递归宏生成所有子项
#define PARENT(R, ...) \
    struct R { \
        R() = default; \
        CHILD_REC(R, __VA_ARGS__) \
    };

// 测试代码
PARENT(ParentA, ChildA, 0, 64);
PARENT(ParentB, ChildA, 32, 1, ChildB, 0, 1);

int main() {
    return ParentB().ChildA.test;  // 可以正常访问,编译通过
}

方案生效的核心逻辑

  1. 绕开自引用限制
    CHILD_REC_HELPER里没有直接调用自身,而是调用CHILD_REC这个中间宏,预处理器会把CHILD_REC当成全新的宏调用,不会触发「自引用忽略」的规则。

  2. 自动终止递归
    _CHILD_REC_DISPATCH利用预处理器的可变参数展开特性:当剩余参数不足3个(也就是没有完整的子项参数时),会自动匹配到CHILD_REC_END空宏,递归流程自动停止。

  3. 完全匹配需求
    预处理器展开后生成的代码和你原来的非递归版本完全一致,每个父类结构体里都会生成对应的子项结构体和成员变量,完全满足你对寄存器位域代码生成的需求。

展开效果验证

以PARENT(ParentB, ChildA,32,1, ChildB,0,1)为例,预处理器最终会展开为:

struct ParentB {
    ParentB() = default;
    struct ChildA_t { int test; }; ChildA_t ChildA;
    struct ChildB_t { int test; }; ChildB_t ChildB;
};

完全符合你的预期,不会出现任何类型说明符错误。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 08:28:08