Preprocessor 测试宏定义是否为空

Preprocessor 测试宏定义是否为空,preprocessor,c-preprocessor,Preprocessor,C Preprocessor,我在tracing.hh中有一组调试宏。它是否生成代码和输出由实际源代码中的宏标志控制: // File: foo.cc #define TRACING 0 #include "tracing.hh" // Away we go . . . TRACEF("debug message"); 标志跟踪应该有一个值;我通常在0和1之间切换 在tracing.h中 #ifdef跟踪将告诉我跟踪已定义 #如果跟踪控制函数宏的定义,如TRACEF() 但如果跟踪没有价值呢?然后#如果跟踪产生错误:

我在tracing.hh中有一组调试宏。它是否生成代码和输出由实际源代码中的宏标志控制:

// File:  foo.cc
#define TRACING 0
#include "tracing.hh"
// Away we go . . .
TRACEF("debug message");
标志跟踪应该有一个值;我通常在0和1之间切换

在tracing.h中

  • #ifdef跟踪
    将告诉我跟踪已定义
  • #如果跟踪
    控制函数宏的定义,如
    TRACEF()
但如果跟踪没有价值呢?然后
#如果跟踪
产生错误:

In file included from foo.c:3:
tracing.hh:73:12: error: #if with no expression
如何测试跟踪是否已定义但没有值?

可能会

#if defined(TRACING) && !TRACING

做这个把戏吗?

根据Matti的建议和更多的戳,我认为问题在于:如果
跟踪
没有价值,我们需要在测试中使用有效的预处理器表达式
#如果…
。这个 表示它必须求值为整数表达式,因此我们需要一个即使缺少其中一个参数也有效的表达式。我最后想到的是:

#if (TRACING + 0)
#  . . .
  • 如果
    跟踪
    有一个数值(如
    #定义跟踪2\n)
    ,则cpp有一个有效的表达式,并且我们没有更改该值
  • 如果
    跟踪
    没有值(如
    #定义跟踪\n
    ),预处理器将
    #If(+0)
    计算为
    false
唯一不能处理的情况是

  • 如果
    跟踪
    具有非数值(即
上的
)。cpp手册说,“非宏的标识符……都被认为是数字零”,其计算结果为
false
。然而,在这种情况下,考虑这一点是更合理的:<代码>真< /代码>值。唯一做正确事情的是布尔文本
true
false

    晚会迟到了,但我发现了一个很好的方法来区分

    #define TRACING 0
    

    像这样:

    #if (0-TRACING-1)==1 && (TRACING+0)!=-2
    #error "tracing empty"
    #endif
    
    如果
    跟踪
    为空,则表达式的计算结果为
    0--1
    =>
    1

    如果
    TRACING
    为0,则表达式的计算结果为
    0-0-1
    =>
    -1

    我在case
    TRACING==-2
    中添加了一个额外的检查,这将使第一个测试通过


    当然,这对字符串文本不起作用。

    我想差不多。请参阅下一个答案:不幸的是,这不起作用。您将遇到相同的问题,其中as跟踪将被删除。您将得到类似这样的结果:“#如果定义(跟踪)&&&!”。因此,“error:operator'!'没有正确的操作数”将在生成时引发。您仍然可以通过使用
    #
    运算符将宏设置为字符串来执行运行时测试。C++11可能能够将其转换为编译时测试(我认为使用
    constexpr
    可能是一种方法),但不是预处理器测试。此外,在Visual Studio 2017中,您无法区分空跟踪和
    跟踪
    等于0
    +0
    不是有效的整数表达式。我把它改成了
    #if(TRACING-0)
    ,现在它就像一个符咒一样工作。谢谢你指出这一点。我没有测试,但我想我们也可以做
    -DTRACING=
    #if (0-TRACING-1)==1 && (TRACING+0)!=-2
    #error "tracing empty"
    #endif