【问题标题】:Test for empty macro definition测试空宏定义
【发布时间】:2011-05-05 09:06:38
【问题描述】:

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

// File:  foo.cc
#define TRACING 0
#include "tracing.hh"
// Away we go . . .
TRACEF("debug message");

标志TRACING应该有一个值;我通常在 0 和 1 之间切换。

在tracing.h中,

  • #ifdef TRACING 会告诉我跟踪已定义。
  • #if TRACING 控制函数宏的定义,如TRACEF()

但是如果 TRACING 没有价值怎么办?然后#if TRACING 产生错误:

In file included from foo.c:3:
tracing.hh:73:12: error: #if with no expression

如何测试 TRACING 是否已定义但没有值?

【问题讨论】:

    标签: preprocessor c-preprocessor


    【解决方案1】:

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

    #define TRACING 0
    

    来自

    #define DTRACING
    

    像这样:

    #if (0-TRACING-1)==1 && (TRACING+0)!=-2
    #error "tracing empty"
    #endif
    

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

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

    我添加了一个额外的检查以防TRACING==-2 使第一次测试通过。

    这当然不适用于字符串文字。

    【讨论】:

    • 是的,我是这个意思。感谢您指出了这一点。我没有测试,但我认为我们也可以做-DTRACING=
    【解决方案2】:

    根据 Matti 的建议和更多的戳,我认为问题是这样的:如果 TRACING 没有值,我们需要在测试 #if ... 中使用有效的预处理器表达式。 Gnu cpp manual 表示它必须计算为整数表达式,因此我们需要一个有效的表达式,即使其中一个参数丢失。我最后想到的是:

    #if (TRACING + 0)
    #  . . .
    
    • 如果TRACING有一个数值(如#define TRACING 2 \n),cpp有一个有效的表达式,我们没有改变这个值。
    • 如果TRACING 没有值(如#define TRACING \n),则预处理器将#if (+0) 评估为false

    唯一不能处理的情况是

    • 如果TRACING 有一个非数字值(ON)。 cpp 手册说“不是宏的标识符......都被认为是数字零,”其计算结果为false。但是,在这种情况下,将其视为true 值会更有意义。唯一正确的是布尔文字 truefalse

    【讨论】:

    • 您仍然可以通过使用 # 运算符将宏设为字符串来进行运行时测试。 C++11 可能能够将其转换为编译时测试(我想使用 constexpr 可能是一种方式)但不是预处理器。
    • 你也没有办法区分空和TRACING等于0
    • 在 Visual Studio 2017 中 +0 不是有效的整数表达式。我把它改成了#if (TRACING - 0),现在它就像一个魅力。
    【解决方案3】:

    #if defined(TRACING) && !TRACING
    

    做这个伎俩?

    【讨论】:

    • 差不多,我想。查看下一个答案:
    • 很遗憾,这不起作用。您将遇到同样的问题,因为 TRACING 将被删除。你最终会得到类似:“#if defined(TRACING) && !”。因此,“错误:运算符'!'没有正确的操作数 " 将在构建时引发。
    猜你喜欢
    • 1970-01-01
    • 2015-10-19
    • 1970-01-01
    • 2010-09-06
    • 2010-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-23
    相关资源
    最近更新 更多