2015-10-28 3 views
2

вот мой код, я нахожу, что «каждый» макрос только перебирает первый элемент и выводит «s1», как заставить его перебирать все элементы?c «каждый» макрос не перебирает все элементы

#include "stdio.h" 

#define each(item, array) \ 
    for (int keep = 1, count = 0, size = sizeof(array)/sizeof *(array); keep && count != size; keep = !keep, count++) \ 
     for (item = array[count]; keep; keep = !keep) 

char *join(char const *ss[]) { 
    char *r = ""; 
    each(char *s, ss) { 
      puts(s); 
     } 
    return (r); 
} 

int main(int argc, char **argv) { 
    char const *ss[] = {"s1", "s2"}; 
    join(ss); 
}; 
+1

Пожалуйста, не писать макросы, как они; не пытайтесь изменить язык C. Вы можете предположить, что каждый программист C знает C. Вы не можете предположить, что они знают или хотят узнать о вашем домашнем, секретном макроязыке. Это очень плохая практика программирования. – Lundin

+0

Не похоже на то, чтобы поместить двойной вложенный цикл в макрос, называемый 'each'. Эта логика более сложна, чем вы можете считать «шаблоном». Кроме того, вы должны указывать имена макросов UPPERCASE, когда вы делаете вещи, которые не являются функциями. (например, макрос 'max' может быть одобрен, если он использует функции GNU C, чтобы избежать оценки его аргументов несколько раз.) –

ответ

1

Если вы звоните each из main, то есть место, где ss определяется, ваша программа работает, как ожидалось:

int main(int argc, char **argv) { 
    char const *ss[] = {"s1", "s2"}; 

    each(char *s, ss) { 
     puts(s); 
    } 
}; 

Это работает, потому что each имеет доступ к ss декларации, так что sizeof a/sizeof *a равно числу элементов в массиве.

Проблема в том, что если вы передадите массив ss в другую функцию (например, join), это decays to pointer. Поскольку ss в join является указателем, sizeof array больше не относится к размеру массива, а выражение sizeof a/sizeof *a дает sizeof(char**)/sizeof(char*), что равно 1 на вашей платформе.

Смотрите также

What is array decaying?

+0

Вы правы, я использую переменные параметры для перезаписи # присоединиться – nwaicaethi

0

Учитывая ниже терминологию

for(initialization statement; condition; update statement) { 
     code/s to be executed; 
} 

Ваш condition имеет заявление keep && count != size;, который проверяет наличие значения keep быть отличны от нуля.

И в update statement вы делаете keep = !keep, что составляет keep значение 0.

Следовательно, ваша петля выходит из одной итерации. Модифицируйте свое состояние в соответствии с циклом несколько раз.

+0

Это не причина, я держу! = держать дважды – nwaicaethi

0

Здесь макрос не создает какие-либо проблемы макросъемки просто место код всякий раз, когда вы использовали,

вам нужно проверить for петли,

size = sizeof(array)/sizeof *(array); 

В заявлении выше sizeof(array) и sizeof *(array) оба дают sizeof указателей. Таким образом, size всегда 1.

Next находится внутри или второй for цикл повторяется только один раз, потому что вы сделали keep = !keep, которые меняют keep = 0;

Так что теперь она завершена первая итерация, она собирается обновить keep = !keep, count++), После этого проверьте состояние keep && count != size в этом

keep = 1; 

count= 1; и

size = 1; 

так завершает цикл, так проверьте свою часть состояния цикла.

если у вас есть намерение просто итерацию для всех элементов в массив символов, то там количество раствора сделать это, я просто листинг один из них изменить в коде

В макро

for (int keep = 1, count = 0, size = sizeof(ss)/sizeof *(ss); ss[count] != "\0"; keep = !keep, count++) \ 

В основная функция

char const *ss[] = { "s1", "s2","\0" }; 

Теперь вы получите как ожидается выход.

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