将点作为参数传递给C宏

时间:2019-12-03 12:29:48

标签: c++ macros c-preprocessor

我在StackOverflow上阅读了不同的相关答案,但是没有一个给我这个问题的答案。 我需要对传递给宏的实体(不一定是字符串)进行串联,并在它们之间使用分隔符(在我的情况下为点)。这是我的代码:

classes/PaymentModule.php line 716

这里是您如何使用它

    #define STR(x) #x
    #define XSTR(x) STR(x)

    #define CONC_(a, b) a ## b
    #define CONC(a, b) CONC_(a, b)

    #define CONC3(_1, _2, _3, S) CONC2(CONC2(_1, _2, S), _3, S)
    #define CONC2(_1, _2, S) CONC(_1, CONC(S, _2))

    #define JOIN_UNDERSCORE(_1, _2, _3) XSTR(CONC3(_1, _2, _3, _))
    #define JOIN_DOT(_1, _2, _3) XSTR(CONC3(_1, _2, _3, .)) // here I pass dot

我可以使用另一种技术来实现这一目标。喜欢:

    std::string underscore = JOIN_UNDERSCORE(one, two, three);
    std::string dot = JOIN_DOT(one, two, three); // this one doesn't compile

,这将适用于点。但是问题是如何通过传递分隔符使其通用。

这里是https://godbolt.org/z/MDxsJS

的播放链接。

2 个答案:

答案 0 :(得分:2)

##运算符的结果必须是有效的预处理器令牌。 one_有效,one.无效。这就是为什么下划线起作用而点不起作用的原因。

如果要创建字符串,则可以使用预处理器字符串文字串联,而不要使用令牌粘贴运算符:

#define STR(x) #x
#define JOIN_UNDERSCORE(_1, _2, _3) STR(_1) "_" STR(_2) "_" STR(_3)

可以一般写为:

#define STR(x) #x
#define JOIN_SYMBOL(_1, _2, _3, symbol) STR(_1) STR(symbol) STR(_2) STR(symbol) STR(_3)
...
const char* underscore = JOIN_SYMBOL(one, two, three, _);
const char* dot = JOIN_SYMBOL(one, two, three, .); 

这不能用于创建变量名,但是点也不能用于创建变量名。

可以通过完全跳过串联来完成此操作,但是这样做有什么好处,我不知道:

#define DUMB_THING(_1, _2, _3, thingie) _1 thingie _2 thingie _3

#include <stdio.h>

int main (void)
{
  typedef struct { int idea; } stupid_t;
  typedef struct { stupid_t stupid; } really_t;
  really_t really;
  DUMB_THING(really, stupid, idea, .) = 42; 
  printf("%d", really.stupid.idea);
}

答案 1 :(得分:-1)

##允许连接有效预处理令牌,从而形成有效预处理令牌。

您可以使用

using Microsoft.Deployment.WindowsInstaller;
std::string pi = CONCSTR2(3, 141592); 33.相同的

都是有效的预处理令牌。但是您不能使用

3.141592

作为std::string dot = JOIN_DOT(one, two, three); (这是您正在执行的第一个串联)不是有效的预处理标记。当您的最终目标是形成字符串时,最好使用并置可用的字符串文字串联。如果您的目标是标识符,则可以使用第一种方法。