2014-12-25 3 views
1

Это, вероятно, не является «лучшей практики», но я хочу добавить свои собственные операторы цикла:Уникальное имя для переменной цикла в макро

#define repeat(count) for(int _repeat_i = 0; _repeat_i < (count); _repeat_i++) 

Тогда это будет работать нормально:

repeat(5) { 
    do_stuff(); 
} 

Но я не могу его вложить:

repeat(5) { 
    do_big_stuff(); 

    repeat(3) { 
     do_little_stuff(); 
    } 
} 

... потому что имена переменных будут сталкиваться.

Любой способ создания уникального имени переменной в макросе?

+0

Не вы обычно нужен индекс цикла внутри цикла? Почему бы не изменить свой макрос, чтобы принять это, таким образом, вручную разрешая столкновения? – Pradhan

+0

Это был бы другой вариант макроса, но здесь мне не нужен индекс (пример - я хочу, чтобы вспышка светодиода 5 раз). Подумайте о примере с рекурсивным макросом - там вам сложно связать имя цикла, но он столкнется с вложенным циклом – MightyPork

ответ

6

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

Пример приведен на: http://rentzsch.tumblr.com/post/12960046342/nearly-hygienic-c-macros-via-counter

Идея заключается в том, чтобы создать макрос, который взять в имени переменной суффикс использовать, затем завернуть, что со вторым макросом, который проходит в __COUNTER__, чтобы создать уникальный суффикс.

+0

Хорошо работает, я попробовал: http: // ideone.com/POevT7 – MightyPork

4

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

for(int _repeat_i = 0; _repeat_i < (5); _repeat_i++) { 
    do_big_stuff(); 

    for(int _repeat_i = 0; _repeat_i < (3); _repeat_i++) { 
     do_little_stuff(); 
    } 
} 

Если вы действительно хотите уникальные имена, хотя, вы можете использовать макрос __COUNTER__ или __LINE__ для создания уникальных имен переменных.

+0

Вы уверены, что это скомпилируется и не вызовет какой-то бесконечный цикл? Вы можете затенять переменную во вложенной области? Извините, я работал с java .. может быть, поэтому я этого не понимаю .. – MightyPork

+0

Да. Вы можете изменять переменные в вложенных областях на C++. –

+0

также в обычном старом C? – MightyPork

5

Общий обходной путь эта проблема передать имя переменной в макрос:

#define repeat(v,count) for(int v = 0; v < (count); v++) 

Теперь вы можете писать такие вещи, как repeat(i,5) и repeat(j,3), чтобы избежать переопределения переменных.

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

#define repeat(count) for(int _repeat_##__LINE__ = 0; _repeat_##__LINE__ < (count); _repeat_##__LINE__++) 

Это не идеально, потому что два repeat(...) заявления по той же линии, что приводит к ошибке.

Однако для большинства практических целей этого макроса будет делать работу:

repeat(2) { 
    repeat(3) { 
     printf("hello\n"); 
    } 
} 

Demo.

+0

Хорошая идея, опция '__COUNTER__', упомянутая Hargobind, выглядит лучше, чем' __LINE__'. – MightyPork

+0

@MightyPork Труднее использовать '__COUNTER__' - вам придется использовать два уровня макросов, потому что иначе вы не сможете повторно использовать имя, потому что счетчик будет увеличиваться. Кроме того, '__COUNTER__' не является стандартным, поэтому ваш код будет подвержен сомнительной переносимости. – dasblinkenlight

+0

На самом деле, следуя идее другого ответа, легко встретить счетчик: http://ideone.com/POevT7 Переносимость в порядке. Думаю, она всегда будет скомпилирована с помощью GCC. – MightyPork

Смежные вопросы