цикл for или while внутри директивы #define - PullRequest
11 голосов
/ 23 апреля 2011

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

Ответы [ 6 ]

10 голосов
/ 23 апреля 2011

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

#define LOOP(start, end)                  \
  for (int i = (start); i < (end); i++) { \
    printf("%d\n", i);                    \
  }
9 голосов
/ 23 апреля 2011

Краткий ответ - «не».Но если у вас есть к, ради любви всего святого , не делайте это:

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

Плохое дзю-джи вокруг.Обратите внимание, что start должно соответствовать lvalue;Вы не сможете назвать это как FOREACH(1,10), или FOREACH((a+b), c), или FOREACH(x++,y++).Все это может привести к ошибке времени компиляции (операнд ++ должен быть l-значением, и ни один из 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, имеющего побочный эффект, который применяется, или от функции, которая вызывается при каждой итерации.

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

4 голосов
/ 23 апреля 2011

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

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

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

#define M \
  while (...) { \
    ...; \
    ...; \
  }
4 голосов
/ 23 апреля 2011
#define something for(;;) printf("hooray, i'm in infinite loop!");


int main() { something }
2 голосов
/ 23 апреля 2011
#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 и поэтому не очень полезно.

1 голос
/ 14 января 2016

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

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