如何编写扩展为包含换行符的cpp宏?
答案 0 :(得分:16)
我正在开发一个涉及大量预处理器宏函数的大型项目,以合成任何不能被模板替换的代码。相信我,我熟悉各种模板技巧,但只要没有可以直接创建代码的标准化,类型安全的元编程语言,我们就必须坚持使用旧的预处理器及其繁琐的宏来解决一些问题。如果没有,则需要写十倍以上的代码。 一些宏跨越许多行,并且在预处理代码中很难读取。因此,我想到了解决这个问题的方法,我想出的是:
假设我们有一个跨越多行的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__
字符串,瞧,你最终得到了预处理后替换宏的结果的可读表示,类似于正是编译器会看到的,除了人为引入的换行符。
答案 1 :(得分:8)
答案 2 :(得分:7)
这是不可能的。只有在查看列表文件或预处理器输出时才会有用。
编写宏以使它们更易于阅读的常用技巧是使用\字符将宏继续到下一行。
我(相信我)已经看到编译器在列表输出的扩展宏中包含新行 - 为了您的利益。这只适用于阅读扩展宏的穷人,试图了解我们真正要求编译器做什么。它对编译器没有任何影响。
C&amp; C ++语言以相同的方式处理字符串之外的所有空格。就像一个分隔符。
答案 3 :(得分:4)
C编译器知道空格,但它不区分空格,制表符或新行。
如果你的意思是我如何在宏中的字符串中有一个新行,那么:
#define SOME_STRING "Some string\n with a new line."
会奏效。
答案 4 :(得分:-2)
使用\
,如下所示:
#define my_multiline_macro(a, b, c) \
if (a) { \
b += c; \
}
答案 5 :(得分:-3)
不太清楚你在这里问的是什么。你想在多行上使用宏吗?
#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 :(得分:-3)
使用行末尾的\。我见过很多C macos,他们使用do ... while(0)
#define foo() do \
{
//code goes here \
\
\
}while(0);
此外,请记住在许多情况下使用父母。
示例:
#define foo(x) a+b
//should be
#define foo(x) (a+b)