Генераторы в C

Путем я сделал должно было потребоваться несколько минут первоначально для осмотра через самый основной материал - перемещение курсора, поиск вперед и назад, переход к следующим и предыдущим словам/предложениям/абзацам, и т.д. Вставка, добавление. Независимо от того, что можно поместиться голову. Затем когда у Вас есть что-то, чтобы сделать, который не должен быть сделан за следующие 15 секунд, заставить себя использовать его.

, Когда Вы довольно довольны основами, медленно изучайте более усовершенствованные команды - особенно те, которые усиливают Ваше предыдущее приобретение знаний (как замена следующих 3 слов или удаление к следующей поисковой цели)

, я люблю использовать VI, как только я учился как. Усовершенствованные команды намного более мощны, чем, что большинство редакторов GUI, кажется, предлагает, и то, что это повсеместно и основано на тексте, и так доступно по ssh, тем лучше.

8
задан Jonathan Leffler 29 October 2009 в 13:50
поделиться

2 ответа

Он отслеживает значение, увеличивая хвост структуры экземпляры mapgen, смешанные с экземплярами times2

Каждый вызов pow2next добавляет еще одну пару к хвосту.

Единственная ценность этого примера - иллюстрация того, как много языков высокого уровня делают для нас и насколько наивная реализация высокоуровневых языков концепции уровней могут убить вашу производительность.

0
ответ дан 5 December 2019 в 20:17
поделиться

Код показывает, как можно сгенерировать произвольную последовательность чисел
с помощью 'генераторов' .

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

Отслеживание происходит в строках

p->next = pow2next;
p->continue_from = 0;

, которые говорят p , что он должен вызвать pow2next , чтобы получить следующий элемент в последовательности
и continue_from = 0 , чтобы указать, что where в начале последовательности.

Когда вы вызываете p-> next (p) , он фактически просто вызывает pow2next с p в качестве параметра. Для первого вызова это просто вернет 1 и увеличит continue_from до 2 .

switch(p->continue_from) {
 case 0:
    p->continue_from = 1;
    return 1;
/* ... */

При втором вызове ( continue_from = 2 ) он создаст новую рабочую структуру map_gen на новой структуре struct pow2s и с помощью функции times2 :

case 1:
  p->g = map(times2,pow2()) ;
  p->continue_from = 2;
  return p->g->next(p->g) ;
/* ... */

Все дальнейшие вызовы проходят через p-> g-> next (p-> g) , который использует times2 и map_gen для получения следующего значение / создайте новые структуры map_gen по мере необходимости. Все отслеживание значений выполняется с помощью элемента структуры continue_from или с использованием кодов возврата.

Показывая интересный подход к генераторам в C, я должен указать, что этот код приводит к утечке памяти! Как видите, новые структуры выделяются с помощью malloc , но они никогда не освобождают .

Я надеюсь, что это объяснение не сбивает с толку, даже если вы только начинаете учиться C.
Если вы действительно хотите разбираться в генераторах, возможно, вам захочется пройти небольшой курс по питону;)

ОБНОВЛЕНИЕ

Как вы сказали в своем комментарии , ни один из генераторов, кажется, никогда не возвращает значение> 2 .
Ключ к увеличению числа кроется в функции map_next :

int map_next(struct mapgen *p) {
    return p->f(p->g->next(p->g));
}

. Вместо того, чтобы возвращать исправление, он применяет номер p-> f ()
(в нашем преобразуйте функцию times2 () в результат p-> g-> next (p-> g) .

Это рекурсивный вызов.

Он будет продолжайте вызывать map_next () для каждого map_gen в списке, пока не дойдете до последнего.
Этот последний элемент вернет фиксированное значение (либо 1 , либо 2 ).
Которая затем передается обратно в предыдущий вызов, который применит к нему times2 () и вернет результат вызывающей стороне, которая, в свою очередь, применит к нему times2 () и вернет результат для его вызывающей стороны .... (вы поняли).

Все эти рекурсивные вызовы суммируются и формируют окончательное значение.
Если вы распечатаете результат каждого вызова pow2next () , вы получите следующее:

/* first call */
  1
pow2next: returning 1
pow2next: returning 2  /* times2(1) */

  2
pow2next: returning 1
pow2next: returning 2 /* times2(1) */
pow2next: returning 4 /* times2(2) */

  4
pow2next: returning 1
pow2next: returning 2 /* times2(1) */
pow2next: returning 4 /* times2(2) */
pow2next: returning 8 /* times2(4) */

 8
pow2next: returning 1
pow2next: returning 2 /* times2(1) */
pow2next: returning 4 /* times2(2) */
pow2next: returning 8 /* times2(4) */
pow2next: returning 16 /* times2(8) */

16 

/* and so on */

Вы можете ясно видеть, как результат самого верхнего вызова передается полностью обратно к первому вызову для формирования результат.

8
ответ дан 5 December 2019 в 20:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: