Есть ли способ написать макрос препроцессора C с переменными аргументами, как это? - PullRequest
0 голосов
/ 02 октября 2019

Я хочу макрос препроцессора C, который может преобразовать это:

if (IN(node->type, BRANCH, CAPTURE_START, CAPTURE_END)) {
    ...
}

в это:

if (node->type == BRANCH || node->type == CAPTURE_START || node->type == CAPTURE_END) {
    ...
}

, что отчасти похоже на оператор MySQL IN. Возможно ли это?

1 Ответ

0 голосов
/ 02 октября 2019

CPP не поддерживает итерацию по списку аргументов. Ближайшей структурой в «C» будет оператор switch, но он не приводит к

  switch (node->type ) {
      case V1:
      case V2:
      case V3:
          ...
   }

. В качестве альтернативы, вы можете получить что-то более подходящее тесту IN, используя Aфункция с функцией vararg. Это ограничения, что (1) тип должен быть известен, и (2) будет специальное значение (в последнем примере), чтобы указать конец списка

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdarg.h>

#define LAST (-1)

bool in_int_set(int v, ...)
{
   va_list ap ;
   va_start(ap, v) ;
   for (;;) {                        // forever
        int s = va_arg(ap, int) ;
        if ( s == LAST ) return false ;
        if ( s == v ) return true ;
   } ;
}

void main(void) {
        printf("A=%d\n", in_int_set(5,      3, 5, 7, LAST)) ;
        printf("B=%d\n", in_int_set(5,      2, 4, 6, 8, 10, LAST)) ;
// From the question about
        if ( in_int_set(node->type,     BRANCH, CAPTURE_START, CAPTURE_END, LAST) ) {
            ...
        }
}
...