Хотя GNU C поддерживает вложенные функции, все равно не будет работать. Вложенные функции в GNU C являются «только нисходящими funarg». Они не лексические замыкания;все в стеке. Когда родительский элемент вложенной функции завершается, эта функция становится мусором;использование возвращенного указателя функции вне этой области не является четко определенным.
(для локальных функций GNU C также требуется исполняемый стек. Они помещают нисходящее замыкание в обычный указатель на функцию C, что требует построения элементамашинного кода в стеке, называемого «батутом».)
Чтобы моделировать лексические замыкания в стандарте C, необходимо поднять все тела функций в область действия файла (без вложенности) и использовать явную структуру данных замыкания, котораясодержит указатель на код и на захваченную среду:
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
struct counting_closure {
/* simulated captured environment */
int count;
/* pointer to code */
int (*lambda)(struct counting_closure *);
};
int counting_lambda(struct counting_closure *clo)
{
/* simulated access to captured lexical */
return clo->count++;
}
struct counting_closure *make_counter(int start)
{
struct counting_closure *clo = malloc(sizeof *clo);
clo->count = start;
clo->lambda = counting_lambda;
return clo;
}
int main(void)
{
struct counting_closure *cntr = make_counter(1);
printf("%d\n", cntr->lambda(cntr));
printf("%d\n", cntr->lambda(cntr));
printf("%d\n", cntr->lambda(cntr));
free(cntr);
return 0;
}