【问题标题】:How to generate a newline in a cpp macro?如何在 cpp 宏中生成换行符?
【发布时间】:2010-09-11 01:37:02
【问题描述】:

如何编写扩展为包含换行符的 cpp 宏?

【问题讨论】:

  • 你能解释一下你为什么要这样做吗?
  • @LouFranco 可能是为了让它更具可读性?
  • 看看下面的答案,很明显你不能。考虑到这一点,问题可能是“你做得很好”。对您来说更好的解决方案(以及使用 C 宏时的常见解决方案)可能是让宏只做它可以做的最少工作,然后将大部分工作交给辅助函数。 宏的强大功能 + 非优化构建中格式良好的功能性 C 代码 = 胜利。
  • 这可能与How to make G++ preprocessor output a newline in a macro? 重复,尽管另一个问题更具体,但它的答案很好,涵盖了这里提出的所有问题。
  • 这对于应该在扩展主体中产生#pragmas 的宏非常有用。 (手头的 OpenMP 案例)

标签: c++ macros c-preprocessor


【解决方案1】:

我正在从事一个大型项目,该项目涉及大量预处理器宏函数来合成任何无法被模板替换的代码。相信我,我熟悉各种模板技巧,但只要没有可以直接创建代码的标准化、类型安全的元编程语言,我们就必须坚持使用好的旧预处理器及其繁琐的宏来解决一些问题如果没有,则需要编写十倍以上的代码。 一些宏跨越多行,在预处理代码中很难阅读。因此,我想到了一个解决这个问题的方法,我想出的是:

假设我们有一个跨多行的 C/C++ 宏,例如在一个名为 MyMacro.hpp

的文件中
// Content of MyMacro.hpp

#include "MultilineMacroDebugging.hpp"

#define PRINT_VARIABLE(S) \
__NL__  std::cout << #S << ": " << S << std::endl; \
__NL__  /* more lines if necessary */ \
__NL__  /* even more lines */

在我定义了这样一个宏的每个文件中,我都包含另一个文件 MultilineMacroDebugging.hpp,其中包含以下内容:

// Content of MultilineMacroDebugging.hpp

#ifndef HAVE_MULTILINE_DEBUGGING
#define __NL__
#endif

这定义了一个空宏__NL__,这使得__NL__ 定义在预处理期间消失。然后可以在某处使用宏,例如 在名为 MyImplementation.cpp 的文件中。

// Content of MyImplementation.cpp

// Uncomment the following line to enable macro debugging
//#define HAVE_MULTILINE_DEBUGGING

#include "MyMacro.hpp"

int a = 10;
PRINT_VARIABLE(a)

如果我需要调试PRINT_VARIABLE 宏,我只需取消注释MyImplementation.cpp 中定义宏HAVE_MULTILINE_DEBUGGING 的行。生成的代码当然不会编译,因为 __NL__ 宏导致未定义,这会导致它保留在已编译的代码中,但是可以对其进行预处理。

现在的关键步骤是使用您最喜欢的文本编辑器将预处理器输出中的 __NL__ 字符串替换为换行符,瞧,您最终会在预处理后得到替换宏的结果的可读表示,这与编译器会看到,除了人为引入的换行符。

【讨论】:

【解决方案2】:

这是不可能的。仅当您查看列表文件或预处理器输出时才有意义。

编写宏以使其更易于阅读的一种常用技术是使用 \ 字符将宏继续到下一行。

我(相信我)已经看到编译器在列表输出的扩展宏中包含新行 - 为了您的利益。这仅对我们这些阅读扩展宏以试图理解我们真正要求编译器做什么的可怜人有用。它对编译器没有影响。

C 和 C++ 语言以相同的方式处理字符串之外的所有空格。就像一个分隔符。

【讨论】:

【解决方案3】:

C 和 C++ 编译器会忽略不带引号的空格(除了 >> 模板问题),因此让宏发出换行符并没有真正意义。您可以通过以反斜杠结束宏的每一行来使宏跨越多行,但这不会输出换行符。

【讨论】:

  • 如果您想检查预处理代码,这实际上是有意义的。然后换行符将有助于评估其调试目的的正确性。
  • 为什么这个答案会得到支持?它没有回答问题。
  • @DavidBaird 同上。答案并没有真正解决问题。
  • @bddicken- 我的情况就是monkeydom所说的,这确实有道理!
  • @DavidBaird @​​​bddicken:我认为“你不能”的答案很容易暗示,即使作者没有直接说出来。看看其他答案,这似乎是事实——没有办法做到这一点,对不起,不。鉴于此,这个答案是验证系统设计的最短和最简洁的答案之一,仅次于“你不能”。
【解决方案4】:

C 编译器可以识别空格,但它不区分空格、制表符或换行符。

如果你的意思是如何在宏的字符串中换行,那么:

#define SOME_STRING "Some string\n with a new line."

会起作用的。

【讨论】:

    【解决方案5】:

    不太清楚你在这里问什么。你想要一个多行的宏吗?

    #define NEWLINE_MACRO(x) line1 \
    line2 \
    line3
    

    此外,如果您想在宏中包含文字:

    #define NEWLINE_MACRO(x) ##x
    

    您在 x 中输入的内容将代替 ##x,因此:

    NEWLINE_MACRO( line1 ) // is replaced with line1
    

    这对于制作自定义全局函数很有帮助,然后只需要更改部分函数名称。

    还有:

    #define NEWLINE_MACRO(x) #x // stringify x
    

    会在 x 周围加上引号

    【讨论】:

      【解决方案6】:

      在行尾使用 \。我见过很多使用 do...while(0) 的 C macos

      #define foo() do \
      {
        //code goes here \
        \
        \
      }while(0);
      

      另外,请记住在许多情况下使用括号。

      例子:

      #define foo(x) a+b
      //should be
      #define foo(x) (a+b)
      

      【讨论】:

      • 宏定义不应包含尾随分号。这使得宏调用看起来更像函数调用。
      【解决方案7】:

      使用\,像这样:

      #define my_multiline_macro(a, b, c) \
      if (a) { \
          b += c; \
      }
      

      【讨论】:

      • 这扩展为“if(a) { b += c }”,没有换行符。用 gcc -E 试试。
      • 确实如此。但它可以让你以多行方式编辑换行符,这就是我认为 OP 想要的
      • 我认为您的意思是输入“让您以多行方式编辑 MACRO”
      猜你喜欢
      • 2011-10-14
      • 2018-07-07
      • 2011-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-16
      • 1970-01-01
      相关资源
      最近更新 更多