gpt4 book ai didi

c - 测试预处理器符号是否在宏中定义

转载 作者:太空狗 更新时间:2023-10-29 15:12:18 25 4
gpt4 key购买 nike

测试预处理器符号是否定义的常用方法是使用#ifdef。但是,#ifdef 不能在宏中使用。如果宏的参数是定义的预处理器符号,我需要一种方法来检入该宏。

例如:

#define TRACE(x,y) if(IS_DEFINED(x)){ std::cout << y; }

这里,TRACE 有两个参数,第一个 x 应该是预处理器符号的名称。如果定义了这样的符号,则应打印第二个参数。我正在寻找不存在的 IS_DEFINED 函数/宏。

用法如下:

#undef BLA
TRACE(BLA,"abc") // "abc" won't be printed, as BLA is not defined
#define BLA 1
TRACE(BLA,"xyz") // "xyz" will be printed, as BLA is a defined symbol

有办法实现吗?也许一些宏观魔法?当然,这些解决方案应该适用于任何符号,而不仅仅是 BLA 或一组硬编码的符号。如果事先知道要检查的符号集,显然很容易。

最佳答案

将字符串化宏(名称)与宏的字符串化(扩展)值进行比较:

#include <iostream>
#include <cstring>

#define TRACE_STRINGIFY(item) "" #item
#define TRACE(macro, message) \
do { \
if (strcmp("" #macro, TRACE_STRINGIFY(macro))) \
std::cout << message << "\n"; \
} while (0)

""#macro 将宏名称扩展为字符串,而 TRACE_STRINGIFY(macro) 首先扩展宏,然后将结果字符串化。如果两者不同,macro 必须是预处理器宏。

对于为自身定义的宏,即 #define FOO FOO,此方法确实失败。此类宏不会被检测为预处理器宏。

大多数编译器应该能够完全优化两个字符串文字的比较。 GNU GCC (g++) 4.8.2 甚至可以使用 -O0(对于 C 的 gcc 也是如此——同样的方法显然也适用于 C)。

这种方法确实适用于类似函数的宏,但前提是您保留括号(如果宏采用多个参数,则保留适当数量的逗号)并且它本身没有定义(例如 #define BAR( x) BAR(x)).

例如:

#define TEST1 TEST1

#define TEST3
#define TEST4 0
#define TEST5 1
#define TEST6 "string"
#define TEST7 ""
#define TEST8 NULL
#define TEST9 TEST3
#define TEST10 TEST2
#define TEST11(x)

#define TEST13(x,y,z) (x, y, z)


int main(void)
{
TRACE(TEST1, "TEST1 is defined");
TRACE(TEST2, "TEST2 is defined");
TRACE(TEST3, "TEST3 is defined");
TRACE(TEST4, "TEST4 is defined");
TRACE(TEST5, "TEST5 is defined");
TRACE(TEST6, "TEST6 is defined");
TRACE(TEST7, "TEST7 is defined");
TRACE(TEST8, "TEST8 is defined");
TRACE(TEST9, "TEST9 is defined");
TRACE(TEST10, "TEST10 is defined");
TRACE(TEST11, "TEST11 is defined");
TRACE(TEST12, "TEST12 is defined");
TRACE(TEST13, "TEST13 is defined");
TRACE(TEST14, "TEST14 is defined");

TRACE(TEST1(), "TEST1() is defined");
TRACE(TEST2(), "TEST2() is defined");
TRACE(TEST3(), "TEST3() is defined");
TRACE(TEST4(), "TEST4() is defined");
TRACE(TEST5(), "TEST5() is defined");
TRACE(TEST6(), "TEST6() is defined");
TRACE(TEST7(), "TEST7() is defined");
TRACE(TEST8(), "TEST8() is defined");
TRACE(TEST9(), "TEST9() is defined");
TRACE(TEST10(), "TEST10() is defined");
TRACE(TEST11(), "TEST11() is defined");
TRACE(TEST12(), "TEST12() is defined");
TRACE(TEST13(,,), "TEST13(,,) is defined");
TRACE(TEST14(,,), "TEST14(,,) is defined");

return 0;
}

哪些输出

TEST3 is defined
TEST4 is defined
TEST5 is defined
TEST6 is defined
TEST7 is defined
TEST8 is defined
TEST9 is defined
TEST10 is defined
TEST3() is defined
TEST4() is defined
TEST5() is defined
TEST6() is defined
TEST7() is defined
TEST8() is defined
TEST9() is defined
TEST10() is defined
TEST11() is defined
TEST13(,,) is defined

换句话说,TEST1 符号未被识别为已定义(因为它是为其自身定义的),TEST11TEST13 也未被识别没有括号。这些是这种方法的局限性。

使用括号形式适用于所有无参数宏(TEST1 除外,即定义给它们自己的宏)和所有单参数宏。如果一个宏需要多个参数,你需要使用正确数量的逗号,否则(比如,如果你试过 TRACE(TEST13(), "..."))你会得到一个编译 -时间错误:“宏 TEST13 需要 3 个参数,仅给定 1 个” 或类似内容。

有问题吗?

关于c - 测试预处理器符号是否在宏中定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26099745/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com