如何将空白添加到concat预处理程序宏?

时间:2018-09-28 19:27:56

标签: c++ c-preprocessor

鉴于以下内容,我如何得到能产生ONE TWO THREE的东西?我似乎无法弄清楚在??中放入什么来产生预期的concat行为。您似乎无法#define留一个空格。

#include <iostream>
#define STRINGIFY(x) #x
#define STRINGIFYMACRO(y) STRINGIFY(y)

#define CONCAT2(X,Y) X ##  Y
#define CONCAT(X,Y) CONCAT2(X,Y)

#define CAT \
ONE     \
TWO


#define DOG \
THREE

#define BAT CONCAT(CONCAT(CAT,?? ),DOG)

int main()
{
    std::cout << STRINGIFYMACRO(BAT) << std::endl;
    return 0;
}

1 个答案:

答案 0 :(得分:1)

##运算符用于组合两个连续的令牌。它不能用于组合非令牌的内容(例如空格),如果结果不是有效的(预处理)令牌,也不能使用它。

换句话说,不要使用##来组合字符串。那不是它的目的,它是行不通的。

请记住,在C ++中,连续字符串将由编译器连接。因此,通常不需要连接字符串的内容。即使必须串联内容,也可以不使用令牌串联而这样做,因为字符串的内容不是令牌。 (仅当您尝试从多个组件创建计算出的#include文件名时才需要这样做。)

要知道的另一件有用的事情是,宏替换中的空格(不在两端)被简化为单个空格字符,由stringify运算符保留。

因此,如果您可以使用单个空格字符,则可以执行以下操作:

#include <iostream.h>
#define STRINGIFY(x) #x
#define STRINGIFY_EXPANDED(x) STRINGIFY(x)

#define CAT ONE TWO
#define DOG THREE
#define BAT CAT DOG

int main() {
  std::cout << STRINGIFY_EXPANDED(BAT) << '\n';
  return 0;
}

Try it online!

否则,您可以将片段分成几部分,然后根据需要串联起来:

#define DOG STRINGIFY(ONE) "   " STRINGIFY(TWO)
#define CAT STRINGIFY(THREE)
#define BAT DOG "\t" CAT

Try it online!