Блоки (расширение языка Си)

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск

Блоки (англ. Blocks) — это добавленное Apple нестандартное расширение языков программирования C/C++/Objective-C, которое использует лямбда-подобный синтаксис для создания замыканий.

Apple создала блоки для облегчения написания приложений для платформы Grand Central Dispatch[1][2], но блоки могут использоваться и вне контекста данной платформы так же, как используются замыкания в других языках программирования. Apple реализовала блоки в собственной ветке компилятора GCC. Языковая поддержка выполнения блоков также доступна как часть проекта LLVM.

Как и функции, блоки могут принимать аргументы и определять собственные локальные переменные. Но в отличие от обычных функций, значения переменных в блоке могут устанавливаться из окружающего констекста (по сути блок «видит» локальные переменные функции, создавшей блок). Определение блока создает скрытый объект, который содержит ссылку на код блока и «снимок» локальных переменных текущего окружения (внешней функции) во время его выполнения. Позже блок может быть вызван так же, как и обычная функция. Блок может быть присвоен переменной, передан функции и ведет себя как обычный указатель на функцию, правда прикладной программист должен пометить блок специальным оператором, если он использует его вне области видимости, где был определен данный блок.

Получив значение блока, код может выполнить его в любой момент, используя синтаксис вызова обычной функции.

Пример[править | править исходный текст]

Простым примером, использующим изменяющееся состояние окружающего контекста, является целочисленный итератор: [3]:

#include <stdio.h>
#include <Block.h>
typedef int (^IntBlock)();
 
IntBlock MakeCounter(int start, int increment) {
	__block int i = start;
 
	return Block_copy( ^ {
		int ret = i;
		i += increment;
		return ret;
	});
 
}
 
int main() {
	IntBlock mycounter = MakeCounter(5, 2);
	printf("First call: %d\n", mycounter());
	printf("Second call: %d\n", mycounter());
	printf("Third call: %d\n", mycounter());
 
	/* because it was copied, it must also be released */
	Block_release(mycounter);
 
	return 0;
}
/* Output:
	First call: 5
	Second call: 7
	Third call: 9
*/

Для компиляции с помощью clang требуются дополнительные опции:

clang -fblocks blocks-test.c -lBlocksRuntime

См. также[править | править исходный текст]

Ссылки[править | править исходный текст]