Управление потоком препроцессора C в зависимости от аргументов функции - PullRequest
2 голосов
/ 20 июля 2011

Что я хочу сделать, это что-то вроде этого

#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 ]

2 голосов
/ 20 июля 2011

У меня это почти работает :) 1001 *

#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();
}

Это также работает на Ideone .

1 голос
/ 20 июля 2011

Нет, ты не можешь сделать это. Значение «code» определяется во время выполнения, а макрос заменяется во время компиляции. Вы должны использовать разные определения макросов.

0 голосов
/ 20 июля 2011

Если ваш компилятор - 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 соответствует пустому аргументу case, а TRIPLE_LOOP_ соответствует другим случаям.Вот тест на ideone .

0 голосов
/ 20 июля 2011

На самом деле вы не можете сделать это, потому что макрос может быть определен только один раз.Вы можете использовать некоторый трюк для достижения этого:

#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, покаПроходящий аргумент.

0 голосов
/ 20 июля 2011

Вы можете сделать это:

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

#define TRIPLE_LOOP()\
SOME_OTHER_CODE

И я думаю, что это сработает:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...