цикл for или while внутри директивы #define

как я могу написать for/while петли внутри

6 ответов


вы, вероятно, искали \ чтобы продолжить определение макроса в нескольких строках:

#define LOOP(start, end)                  \
  for (int i = (start); i < (end); i++) { \
    printf("%d\n", i);                    \
  }

короткий ответ: "нет". Но если ты ... --15-->есть к, ради всего святого не этого:

#define FOREACH(start, end)                         \
      for (; (start) < (end); (start)++)            \
      {                                             \
        // do something interesting                 \
      }                                             

плохой juju весь путь вокруг. Обратите внимание, что start должны соответствуют lvalue; вы не смогли бы назвать это как FOREACH(1,10) или FOREACH((a+b), c) или FOREACH(x++,y++). Все это приведет к ошибке времени компиляции (операнд ++ должно быть lvalue, и ни один из 1, a+b или x++ право). Зовущий это как FOREACH(x, y++) будет делать то, что вы действительно не хочу этого делать. Точно так же вы не хотели бы называть это как FOREACH(x, y()).

вы можете защитить от этих проблем до некоторой степени, делая что-то вроде

#define FOREACH(start, end)                        \
do {                                               \
  int i;                                           \
  int j = end;                                     \
  for (i = start; i < j; i++)  {                   \ 
    // do something interesting                    \
  }                                                \
} while (0)

по сути, вы создаете локальные переменные, соответствующие макроса аргументы. Это защищает от start не будучи lvalue, и против end имеющий побочный эффект, который применяется или является функцией, которая вызывается каждая итерация.

но если вы пытаетесь инкапсулировать цикл, который часто вызывается,положил его в свою собственную отдельную функцию. Это безопаснее и проще понять и поддержать.


#define something for(;;) printf("hooray, i'm in infinite loop!");


int main() { something }

поскольку C не требует, чтобы операторы были на отдельных строках, вы можете просто сжать вместе в одну длинную строку:

#define M while (...) { ...; ...; }

или вы можете избежать новых строк в определении макроса:

#define M \
  while (...) { \
    ...; \
    ...; \
  }

#define foo(x) do { \
    for(x=0;x<4;x++) x; \
    } while(0) // note lack of trailing ;

или в gnu c:

#define foo(x) ({ \
    for(x=0;x<4;x++) x; \
    })

последнее можно использовать как выражение, хотя это имеет тип void и, следовательно, не очень полезно.


Это было бы более общим для цикла

#include <stdio.h>
#include <string.h>

#define for_loop(start, end, incr) for(i = start; \
                                        i < end;  \
                                         i += incr)

int main()
{
  int i=0, j=5;

  for_loop(i, j, 1)
    printf("%d\n", i+1);

  return 0;
}