Инициализация массива C с помощью макроса - PullRequest
3 голосов
/ 29 октября 2009

Справочная информация о вопросе:
void dash(int *n, char c) - рисовать символы c, разделенные '+'.
Параметр n представляет собой массив целых чисел, например, {1, 3, 2} и '-' для c должны давать "+ - + --- + - +", что прекрасно работает. Чтобы использовать тире, я делаю {int f={1, 3, 2}; dash(f, '-');}, что делает конструкцию копируемой и вставляемой.

Сам вопрос:
Чтобы избежать копирования и вставки я хотел сделать #define F(X, Y) {int f=X; dash(f, Y);}, в результате чего получается F({1, 3, 2}, '-').
К сожалению, компилятор жалуется, что F получает 4 (длина массива + 1) аргумента вместо 2.

Так как же вы можете указать {1, 3, 2} в качестве параметра для макроса?

Ответы [ 4 ]

5 голосов
/ 29 октября 2009

Макросы Variadic являются функцией C99.

#define F(Y,...) dash((int[]){__VA_ARGS__},Y)

Так как же вы можете дать {1, 3, 2} как параметр макросу?

F('-',1,3,2);
4 голосов
/ 29 октября 2009

Вот моя версия:

#include <stdio.h> 

void dash(int len, int *n, char c){
  int i;
  printf("dash( %i, {", len );
  for( i=0; i<len-1; i++ )
    printf(" %i,", n[i] );
  printf(" %i }, '%c')\n", n[i], c );
}

#define NOPAREN(...) __VA_ARGS__ 
#define F1(arr,char)  { int f[]={NOPAREN arr}; dash(sizeof(f)/sizeof(f[0]),f,char); } 

#define F2(char,...)  { int f[]=__VA_ARGS__;   dash(sizeof(f)/sizeof(f[0]),f,char); } 

int main(void){
  F1( (1,3,2), '-' );
  F2( '-', {4,6,5} );
}

Результат:

dash( 3, { 1, 3, 2 }, '-')
dash( 3, { 4, 6, 5 }, '-')
1 голос
/ 29 октября 2009

Вместо того, чтобы пытаться использовать макрос для настройки и выполнения этих вызовов, я, вероятно, рассмотрю возможность изменения интерфейса на dash(), чтобы использовать varargs:

#include <stdarg.h>

void dash( char c, ...)
{
    // ...
}


int main() {
    dash( '+', 1, 3, 2, -1);   // note: negative number indicates 
                               //   the end of the list of numbers
    return 0;
}

Использование varargs - не лучшая вещь в мире (их сложно использовать и они небезопасны), но я думаю, что это будет лучше, чем макрокоманда, которую вы пытаетесь создать.

Кроме того, помните, что даже если вы придерживаетесь своего текущего интерфейса для dash() и придумали макрос, который делает то, что вы хотите, вам все равно нужен способ указать конец последовательности чисел, которые нужно передать в dash(). В противном случае у dash нет возможности узнать, когда он достиг конца массива. У вас есть несколько вариантов:

  • использовать значение часового, например, 0, -1 или любое отрицательное число (как в примере vararg выше)
  • передать число элементов в массиве в качестве другого аргумента
  • устанавливает размер массива как часть интерфейса dash(). В вашем примере dash() может потребовать передачи массива из 3-х целых чисел. Ни больше, ни меньше (на самом деле больше будет в порядке - они просто не будут использоваться). Если бы вы сделали это, исправление вашего макроса было бы намного проще, но я подозреваю, что вы не хотите, чтобы dash вел себя.
0 голосов
/ 29 октября 2009

Вы можете передать { 1, 3, 2 } в качестве аргумента макросу, если вы определите { 1, 3, 2 } как другой макрос

#define PARAMS { 1, 3, 2 }
F(PARAMS, '-')
#undef PARAMS

К сожалению, кажется, что нет прямого способа сделать буквально то, что вы просите, т.е. передать конкретно { 1, 3, 2 } в этой конкретной форме. Возможно, стоит перейти на альтернативные методы, в том числе специфичные для C99, предложенные в других ответах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...