【问题标题】:Forcing preprocessor error with macro使用宏强制预处理器错误
【发布时间】:2014-01-10 22:19:03
【问题描述】:

有没有一种方法可以强制 C++ 中的预处理器宏发出错误?我想做的是定义一个宏UNKNOWN。我正在为机器人编写一些代码,但我还不知道所有电子设备的插入位置。我希望能够在某些头文件中定义端口,例如

const int MOTOR_PORT = 1;
const int FAN_PORT = 2;
//etc.

但是,当我到达一个我还不知道的端口时,我希望能够编写类似的东西

const int LED_PORT = UNKNOWN;

在调试模式下,UNKNOWN 将被定义为任意值,例如 0。但是,在发布模式下编译时,我希望它在使用 UNKNOWN 时抛出错误,因此未分配的端口不会' t 最终发布。我知道我可以使用#error 指令来强制出错,但是我可以在宏中做类似的事情吗?

我已经看到使用static_assert 的解决方案,但很遗憾我不能在这个平台上使用 C++11。

【问题讨论】:

  • 你可以试试BOOST_STATIC_ASSERT。
  • 我没有使用 boost,也不愿意为此添加另一个依赖项。
  • 如果您只是省略定义 UNKNOWN 或将其定义为空,则此处的特定代码将无法编译。甚至只是#define UNKNOWN (1/0)
  • 理想情况下,我希望保留#error 发出自定义错误消息的能力,而不仅仅是一个不相关的错误。
  • @WilliamKunkel 如果您只需要在使用时出现#error,则无法做到这一点。如果你这样做了#define FAN_PORT SORRY_THE_FAN_PORT_IS_NOT_AVAILABLE,你可能会强制出现一些描述性的链接错误

标签: c++ debugging macros c-preprocessor


【解决方案1】:

由于#error 不能由宏扩展产生,因此您可以确保宏扩展为必须诊断的内容,例如语法错误。

例如:

#ifdef RELEASE
#define UNKNOWN @Invalid_use_of_UNKNOWN
#else
#define UNKNOWN 0
#endif

const int MOTOR_PORT = 1;
const int FAN_PORT = 2;
const int LED_PORT = UNKNOWN;

int main(void) {
    int x = LED_PORT;
}

@ 字符不是 C 的基本字符集的一部分,因此它在注释、字符常量或字符串文字之外的出现总是会导致错误消息。 ($ 可以工作,除了在标识符中接受$ 是一种常见的扩展。` 可能也可以工作,但@ 更突出。)

我已经定义了宏,所以它会使用 gcc 生成合理的错误消息:

c.c:9:1: error: stray ‘@’ in program
c.c:9:22: error: ‘Invalid_use_of_UNKNOWN’ undeclared here (not in a function)

和叮当声:

c.c:9:22: error: expected expression
const int LED_PORT = UNKNOWN;
                     ^
c.c:2:17: note: expanded from:
#define UNKNOWN @Invalid_use_of_UNKNOWN
                ^
1 error generated.

(有一个_Pragma 运算符对应于#pragma 指令。如果也有一个_Error 运算符就好了,但没有。)

【讨论】:

    【解决方案2】:

    您可以除以零,这将引发编译器错误: #define UNKNOWN 0/0

    【讨论】:

    • 理想情况下,我希望保留#error 发出自定义错误消息的能力。
    • 恐怕这是不可能的,不幸的是static_assert是你需要的东西,我们也不能将预处理器指令扩展到另一个指令。
    • 这不是便携式的。除以零会导致未定义的行为,因此无法保证它会停止编译。
    【解决方案3】:

    好吧,这不会产生像#error这样的编译器错误消息,但会在调试中编译并在发布时失败:

    #ifdef _DEBUG
    #   define UNKNOWN 1
    #else
    #   define UNKNOWN
    #endif
    const int port1 = UNKNOWN; // fail in release
    

    【讨论】:

      【解决方案4】:

      sizeof 运算符不能应用于不完整的类型,所以试试这个:

      // Declared, but not defined anywhere.
      struct illegal_use_of_unknown_macro;
      #define UNKNOWN (sizeof (illegal_use_of_unknown_macro))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-02
        • 2021-12-29
        • 2018-06-12
        • 2015-04-15
        • 2010-10-11
        相关资源
        最近更新 更多