我想在 #warning 指令中打印宏值(展开宏)。
例如,对于以下代码:
#define AAA 17
#warning AAA = ???
期望的编译时输出应该是
warning: AAA = 17
我应该使用什么来完成???,或者说,我应该如何修改代码?
我想在 #warning 指令中打印宏值(展开宏)。
例如,对于以下代码:
#define AAA 17
#warning AAA = ???
期望的编译时输出应该是
warning: AAA = 17
我应该使用什么来完成???,或者说,我应该如何修改代码?
#pragma message
。#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define AAA 123
#pragma message "content of AAA: " STR(AAA)
int main() { return 0; }
输出可能如下所示:
$ gcc test.c
test.c:5:9: note: #pragma message: content of AAA: 123
#pragma message("content of AAA: " STR(AAA))
^
供参考:
#pragma message
而不是 #message
或 #warning
。 - Fantastory#pragma message
可以生成警告就太好了。 #pragma GCC diagnostic warning "message "
不允许它(https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html)。 - pevik#define STR_HELPER(...) #__VA_ARGS__``#define STR(...) STR_HELPER(__VA_ARGS__)
- Cameron Tacklind#define N 77
#define __STRINGIFY(TEXT) #TEXT
#define __WARNING(TEXT) __STRINGIFY(GCC warning TEXT)
#define WARNING(VALUE) __WARNING(__STRINGIFY(N = VALUE))
#if N == 77
_Pragma (WARNING(N))
#endif
#if (AAA < SOMETHING) && (AAA > SOMETHING_ELSE)
#error AAA is bad.
#endif
我认为对于程序员来说,这已经足够详细了。但是,如果你真的想要更多细节并且你有一个现代的C编译器,你可以使用static_assert。然后你就可以实现接近你想要的效果:
#include <assert.h>
#define xstr(s) str(s)
#define str(s) #s
#define err_msg(x) #x " is " xstr(x)
#define AAA 17
static_assert(AAA != 17, err_msg(AAA));
这个宏混乱应该会打印 AAA 是 17。关于这些宏的工作原理的解释可以在这里找到。
我不确定 static_assert 是否包含在 C99 或 C11 中,但它肯定在 C11 中。您可能需要使用一些 GCC 扩展来启用它。
HAL_SYSTEM_RESET()
宏从实际控制寄存器写入重新定义为“while(1)”以便我可以使用调试器检查状态),那么我希望确保该构建永远不会到达实际环境。我仍然需要它构建以使测试工作。当然,只有在生产构建中没有警告的情况下才有效... - Jostikas很多时候我会让我的Makefile生成一个名为generated.h的本地文件,其中包含所需的定义。
generated.h: Makefile echo >generated.h "// 警告:生成的文件。请改变Makefile" date >>generated.h '+// 生成于 %Y-%m-%d %H:%M:%S' echo >>generated.h "#if AAA == AAA_bad" echo >>generated.h "#warning \"AAA = $(AAA_bad)\"" echo >>generated.h "#endif"
需要使用#include "generated.h"来引用它。
当然,您可以在此处添加任何复杂性,但如果行数超过几行,则可能需要将复杂性放入单独的脚本中,因为混乱的Makefile可能会成为可怕的维护问题。稍加想象,您就可以从少量输入中生成大量测试。
将generated.h目标依赖于Makefile是至关重要的,以确保如果目标中的指令发生更改,则重新制作generated.h。如果您有一个单独的generated.sh脚本,那么它也将在依赖项列表中。
免责声明:未进行真实测试。
另一种简单的方法是,特别是当您处理Makefile项目(如linux、u-boot、qemu等)时,您可以查看文件的预处理结果。
例如,
要查看arch/arm64/kernel/head.S
的预处理文件,
您可以执行make arch/arm64/kernel/head.s
。(小写s)。
要查看foo/bar/baz.c
的预处理文件,
您可以执行make foo/bar/baz.i
所有宏都会扩展到最终值。
#error
来处理这样的情况,它不会扩展任何宏,只是字面上打印文本并停止编译。你到底想用这个做什么?我能帮你实现什么目的? - Alexey Frunze#if A == 1\#error A = 1\#elif A == 2\#error A = 2\#endif
。 - Alexey Frunze