我想在C中编写一个带有参数控制的条件定义。
像这样的东西:
#define RTL_REG(reg_name,inst) \
inst == 0 ? DUT_0_##reg_name : \
inst == 1 ? DUT_1_##reg_name : \
inst == 2 ? DUT_2_##reg_name : \
inst == 3 ? DUT_3_##reg_name : \
DUT_0_##reg_name
但是代码没有按照我想要的方式工作。基本上它是用inst的值代替define。
我想要的是:
RTL_REG(CLK_EN,0) -> *DUT_0_CLK_EN*
RTL_REG(CLK_EN,1) -> *DUT_1_CLK_EN*
我得到了什么:
RTL_REG(CLK_EN,0) -> 0
你能帮我一些C专家吗?
注意:在定义的开头和结尾也尝试添加(),但是再次,“(”来自定义替换!
预处理器不支持条件表达式(如?:
)。而是使用单独的函数宏来连接组件:
#define JOIN4(a, b, c, d) a##b##c##d
#define RTL_REG(name, inst) JOIN4(DUT_, inst, _, name)
随后,RTL_REG(CLK_EN, 0)
扩展到DUT_0_CLK_EN
,RTL_REG(CLK_EN, 1)
扩展到DUT_1_CLK_EN
。
类函数宏调用意味着在连接之前由预处理器评估宏参数。这意味着如果你添加一个像这样的定义
#define CLK_EN CLOCK_ENABLE
然后RTL_REG(CLK_EN, 2)
扩展到DUT_2_CLOCK_ENABLE
。如果你进一步添加
#define DUT_ WEIRDPREFIX_
然后RTL_REG(CLK_EN, 3)
扩展到WEIRDPREFIX_3_CLOCK_ENABLE
。
假设你不能使用相同的前缀(DUT_0
,DUT_1
)。别担心;你只需要添加一层类似函数的宏调用,并重新定义前缀:
#define JOIN3_(a, b, c) a ## b ## c
#define JOIN3(a, b, c) JOIN3_(a, b, c)
#define RTL_REG(name, inst) JOIN3(DUT_ ## inst, _, name)
然后,如果你说这些额外的定义,
#define DUT_0 FIRST
#define DUT_1 SECOND
#define CLK_EN CLOCK_ENABLE
然后RTL_REG(CLK_EN, 0)
扩展到FIRST_CLOCK_ENABLE
,RTL_REG(CLK_EN, 1)
扩展到SECOND_CLOCK_ENABLE
。当然,如果你做其他定义,比如
#define FIRST_CLOCK_ENABLE foo(1)
#define SECOND_CLOCK_EANBLE bar(2)
然后RTL_REG(CLK_EN, 0)
确实扩展到foo(1)
,RTL_REG(CLK_EN, 1)
扩展到bar(2)
。
如果中间术语已被定义为宏,您只需要小心,不要太惊讶。如果您正在使用GCC,则可以运行gcc -dD -E source-or-header-file
以获取包含所有宏定义语句的预处理源。