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

Как написать цикл for/while внутри директивы #define в C?

Ответ 1

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

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

Ответ 2

Короткий ответ - "не надо". Но если вам нужно, потому что любовь ко всему этому священному не делает делать это:

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

Бад-Джуджу на всем пути. Обратите внимание, что 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, имеющий побочный эффект, который применяется или является функцией, вызываемой каждой итерацией.

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

Ответ 3

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


int main() { something }

Ответ 4

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

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

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

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

Ответ 5

#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 и, следовательно, не очень полезно.

Ответ 6

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

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