【发布时间】:2021-11-30 08:37:57
【问题描述】:
我正在尝试找到从源代码中提取评估定义列表的最佳方法。
我发现了一些关于如何在编译时评估宏的问题,但我特别希望提取每个#define 的结果以转储到文件中。
这里是问题的一些示例代码:
#define VALUE1 0x01
#define VALUE2 0x10
#define VALUE3 VALUE1 | VALUE2
int main(void) {
printf("VALUE01: 0x%02X\n", VALUE1);
printf("VALUE02: 0x%02X\n", VALUE2);
printf("VALUE03: 0x%02X\n", VALUE3); //prints evaluated VALUE3
}
从技术上讲,示例代码可以实现我正在寻找的内容,但是很麻烦,并且需要编写脚本来生成和维护。理想情况下,已经有一个我忽略的编译器标志可以做到这一点,因为它已经必须评估宏,但我找不到。 是否有任何其他编译器工具可用于实现此目的?
This 回答的问题是我找到的最接近的答案,并为我提供了转储所有定义的能力,但它会转储源代码中看到的未评估形式:
$ gcc -dM -E test.c | grep "VAL"
#define VALUE1 0x01
#define VALUE2 0x10
#define VALUE3 VALUE1 | VALUE2
.... (and all the other preprocessor defines)
【问题讨论】:
-
要清楚
#define VALUE3 VALUE1 | VALUE2并不意味着VALUE3的计算结果为VALUE1 | VALUE2。这意味着令牌VALUE3将被字符串VALUE1 | VALUE2替换,其中VALUE1和VALUE2将替换为它们各自的定义。所以VALUE3将是0x01 | 0x10(而不是0x11)。在最终评估中如何处理它取决于在代码中使用它的上下文。这不包括 rici 在他的回答中引用的额外复杂性。 -
假设没有额外的复杂性(没有运行时依赖、重新定义等),是否有任何直接的方法可以评估为
#define VALUE3 0x11?我问,因为在我的示例中,编译器似乎在“评估”#define。执行objdump -d <object file>时,我可以在反汇编中看到生成的0x11 -
评估
VALUE3到0x11只有知道您将VALUE3扩展的上下文限制为特定情况才有意义。例如,表达式x = VALUE3肯定可以替换为x = 0x11。但是,如果您有x = VALUE3 - 1,这与x = 0x10不同,因为+的运算符优先级高于|。它不涉及任何重新定义或复杂性。这只是上下文。因此,假设VALUE3通常评估为0x11并不是很有用。 -
总的来说,我完全同意。但我确实有一个非常具体的用例,想知道
VALUE3的评估结果。似乎除了创建一个脚本来提取#defines并像示例中那样评估它们之外,没有直接的方法。