C预处理器:在#warning中扩展宏

时间:2012-09-28 09:35:46

标签: c gcc c-preprocessor

我想在#warning指令中打印一个宏值(展开宏)。

例如,对于代码:

#define AAA 17
#warning AAA = ???

所需的编译时输出

warning: AAA = 17

我使用什么???,或者,我如何扩充代码?

4 个答案:

答案 0 :(得分:45)

您可以使用预处理程序指令#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))
         ^

供参考:

答案 1 :(得分:7)

我不建议使用#warning,因为它不是标准的C.此外,你想要警告的是什么,但不会抛出错误?警告通常是编译器在您做一些可疑的事情时使用的东西,我们完全是危险的,但C标准允许这样做。在正常的应用程序中你没有这样的情况,你会希望它完美地编译或根本不编译。因此我使用标准的#error而不是非标准的#warning。

您无法输入预处理器定义的实际内容。这样的事情就足够了:

#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.可以找到关于这些宏如何工作的解释here

我不确定static_assert是否包含在C99或C11中,它肯定在C11中。您可能必须使用某些GCC扩展来启用它。

答案 2 :(得分:7)

如果您确实要发出警告,以下内容也会有效。但是,它取决于启用C99(适用于gcc 4.8.2或更高版本,未在早期版本上测试):

#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

答案 3 :(得分:2)

很多时候,我的Makefile会生成一个包含所需定义的本地generated.h文件。

generated.h:  Makefile
        echo >generated.h "// WARNING: generated file. Change Makefile instead"
        date >>generated.h '+//   generated on %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可能会很可怕 维修问题。通过一点想象力,你可以通过一点输入产生大量测试的循环。

如果目标中的指令发生了变化,那么generate.h的目标依赖于Makefile对于确保generate.h重新生成是至关重要的。如果你有一个单独的generated.sh脚本,它也会在依赖列表中。

免责声明:未进行真实测试。