C预处理器流控制取决于函数参数

时间:2011-07-20 10:49:43

标签: c arguments c-preprocessor flow-control

我想做的是这样的事情

#define TRIPLE_LOOP(code)\
//if there is something in code \
for(...) for(...) for(...) { code }\
//if code is empty then\
SOME_OTHER_CODE

这样

TRIPLE_LOOP(printf("muhahaha"))

将在输出中的三重循环内生成printf 和

TRIPLE_LOOP()

将生成SOME_OTHER_CODE 这可能吗?

5 个答案:

答案 0 :(得分:2)

这几乎对我有用:)

#include <stdio.h>

#define NARGS2(_1, N, ...) N
#define NARGS(...) NARGS2(__VA_ARGS__, 1, 0)
#define TRIPLELOOP(...)                         \
      do {                                      \
        if (NARGS(__VA_ARGS__)) {               \
          int i, j, k;                          \
          for (i=0; i<2; i++) {                 \
            for (j=0; j<2; j++) {               \
              for (k=0; k<2; k++) {             \
                __VA_ARGS__;                    \
              }                                 \
            }                                   \
          }                                     \
        } else {                                \
          printf("NO ARGS");                    \
        }                                       \
      } while (0)

int main(void) {
  TRIPLELOOP(printf("haha"); puts("!"));
  TRIPLELOOP();
}

它还works at ideone

答案 1 :(得分:1)

不,你不能这样做。 “代码”的值在运行时定义,而宏在编译时被替换。您必须使用不同的宏定义。

答案 2 :(得分:0)

实际上你不能这样做,因为宏只能定义一次。您可以使用一些技巧来实现这一目标:

#define TRIPLE_LOOP(CONDITION, ...)\
if(CONDITION) {\
for(...) for(...) for(...) { __VA_ARGS__; }\
} \
else {\
SOME_OTHER_CODE \
}

用法:

TRIPLE_LOOP(true, printf("muhahaha"));  // `true` can be 1
TRIPLE_LOOP(false);  // `false` can be 0

但请确保在传递参数时始终传递正确的bool变量true / false

答案 3 :(得分:0)

如果您的编译器是gcc或MSVC,则以下代码可能符合此目的。

#define EXPAND( x ) x /* for MSVC */
#define CONCAT_( x, y ) x ## y
#define CONCAT( x, y ) CONCAT_( x, y )
#define CAR_( x, ... ) x
#define CAR(...) EXPAND( CAR_( __VA_ARGS__ ) )
#define VA_ARGS_(...) , ##__VA_ARGS__
#define VA_ARGS(...) VA_ARGS_( __VA_ARGS__ )
#define IS_EMPTY(...) CAR( VA_ARGS( __VA_ARGS__ ) 1 )

#define TRIPLE_LOOP(...) \
  CONCAT( TRIPLE_LOOP_, IS_EMPTY(__VA_ARGS__) )(__VA_ARGS__)
#define TRIPLE_LOOP_1(...) SOME_OTHER_CODE
#define TRIPLE_LOOP_(...) for(...) for(...) for(...) { __VA_ARGS__; }

TRIPLE_LOOP_1对应于空参数案例,TRIPLE_LOOP_ 对应于其他情况。 这是对ideone的测试。

答案 4 :(得分:-1)

你可以这样做:

#define TRIPLE_LOOP(code)\
for(...) for(...) for(...) { code }\

#define TRIPLE_LOOP()\
SOME_OTHER_CODE

我认为它会起作用:)