C 如何使#if#endif成为宏的一部分

C 如何使#if#endif成为宏的一部分,c,macros,C,Macros,当我像这样使用这个宏时 #define M(N)\ #if N == 5\ /*several lines of code that Can't be replaced with a tertnary operator*/ #else\ N;\ #endif 我希望输出是 M(5); 但它没有编译 它不能编译我一点也不奇怪:我知道“if”不能在延续行即“\”上使用 我也试过了 // everything within the #if #else

当我像这样使用这个宏时

#define M(N)\
#if N == 5\
    /*several lines of code that 
      Can't be replaced with a   
      tertnary operator*/
#else\
    N;\
#endif
我希望输出是

M(5);
但它没有编译

它不能编译我一点也不奇怪:我知道“if”不能在延续行即“\”上使用

我也试过了

// everything within the #if #else block
如果不起作用,就使用POUND_

这可能吗


是否有一些漂亮的Boost预处理器的东西可以使用?

宏定义不能包含预处理器指令(任何以
开头的指令)

要有条件地扩展到某些值,需要相当复杂的宏观学,并且可能并不总是按照您想要的方式进行。上面的例子可以这样写:

#define POUND_IF #if
但这是难以置信的脆弱。您只能使用某些类型的表达式作为
M
的参数,例如,它们必须具有允许串联的语法结构,并且不允许使用未包装的逗号,并且只适用于预定值(例如,使用此方法无法与比简单数字更复杂的内容进行比较,因为无法从更复杂的表达式中生成宏名称)


但从原则上讲,这是可以做到的。你只需要成千上万行宏定义就可以覆盖像这样琐碎的情况之外的一组有用的情况。你可以通过使用或这样的元编程库来获得这些情况,但如果你的语法稍有失误,就要准备好面对模糊的错误消息。

简而言之,你不能t、 但是,您可以使用优化器:

#define ONE_OR_TWO(...) ONE_OR_TWO_(__VA_ARGS__, 2, 1,)
#define ONE_OR_TWO_(_1, _2, X, ...) X
#define CAT(A, B) CAT_(A, B)
#define CAT_(A, B) A ## B

#define M(N) CAT(IF_, ONE_OR_TWO(CAT(IS_, N)))({\
    code; \
    code; \
}, N)
#define IS_5 ,
#define IF_1(A, B) B
#define IF_2(A, B) A

M(5);  //-> { code; code; }
M(8);  //-> 8

如果编译器可以确定运行代码时
N
的值将为5(例如,您编写
M(5)
),则只有
if
主体中的代码才会包含在生成的代码中。如果编译器可以确定
N
的值在代码运行时不会是5,则它将只生成
else
子句主体中的代码。如果无法确定值是什么,则预处理器将不会您也可以这样做,但编译器将包含所有代码。

我认为您不能这样做。但是为什么不使用常规的if和else?(或三元运算符)如果if表达式在编译时是可计算的,编译器应该优化掉死分支。我同意在这个简单的例子中你是对的。我真正的用途是在#if块中有几行代码。我想我应该更正它,使它代表我的用例。编译器需要在compi计算常量表达式因此,如果这是针对可执行语句的(与声明相反,声明是
#if
的主要原因),那么在C条件下使用宏进行此操作实际上没有任何好处-编译器将在宏可以工作的任何情况下删除未使用的分支。因此,如果您编写
if(x>y)M(3);否则M(5)
您的代码仍将编译。有关详细信息,请参阅。
#define M(N)\
    do { if (N == 5) { \
    /*several lines of code that 
      Can't be replaced with a   
      ternary operator*/ \
    } else { N; } } while (0)