45

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

例如,对于代码:

#define AAA 17
#warning AAA = ???

所需的编译时输出将是

warning: AAA = 17

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

4

5 回答 5

56

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

以供参考:

于 2012-09-28T10:22:44.157 回答
9

如果您真的想发出警告,以下内容也可以。但是,这取决于是否启用了 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
于 2015-03-27T10:58:27.190 回答
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 is 17。关于这些宏如何工作的解释可以在这里找到。

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

于 2012-09-28T11:26:57.583 回答
2

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

生成的.h:生成文件
        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)\""
        回声>>生成.h“#endif”

#include "generated.h" 的需求是显而易见的。

当然,您可以在这里调整任何复杂性,但如果它变得多于几行,您可能希望将复杂性放入单独的脚本中,因为混乱的 Makefile 可能是一个可怕的维护问题。有了一点想象力,您就可以让循环从少量输入中生成大量测试。

让 generated.h 目标依赖于 Makefile 对于确保在目标中的指令发生更改时重新制作 generated.h 至关重要。如果您有一个单独的 generate.sh 脚本,它也将在依赖项列表中。

免责声明:未经真实测试。

于 2012-09-28T10:22:18.203 回答
0

另一个简单的方法是,尤其是在处理 Makefile 项目(如 linux、u-boot、qemu、..)时,可以看到文件的预处理结果。
例如,

要查看 的预处理文件arch/arm64/kernel/head.S
您可以执行 make arch/arm64/kernel/head.s。(小s)。

要查看的预处理文件foo/bar/baz.c
您可以执行 makefoo/bar/baz.i

宏都扩展为最终值。

于 2022-02-11T07:39:06.287 回答