Блоки - нестандартное расширение, добавленное Apple Inc. - Реализации Clang языков программирования C, C ++ и Objective-C, в которых используется лямбда-выражение - как синтаксис для создания замыканий в этих языках. Блоки поддерживаются для программ, разработанных для Mac OS X 10.6+ и iOS 4.0+, хотя среды выполнения сторонних производителей позволяют использовать их в Mac OS X 10.5 и iOS 2.2+, а также в системах сторонних производителей.
Apple разработала блоки с явной целью облегчить написание программ для потоковой архитектуры Grand Central Dispatch, хотя она не зависит от этой архитектуры и может использоваться почти таким же образом как закрытия на других языках. Apple реализовала блоки как в своей собственной ветке GNU Compiler Collection, так и во внешнем интерфейсе компилятора Clang LLVM. Language runtime library поддержка блоков также доступна как часть проекта LLVM. Группа Khronos использует синтаксис блоков для постановки ядер в очередь из ядер начиная с версии 2.0 OpenCL.
. Как и определения функций, блоки могут принимать аргументы и объявлять свои собственные переменные внутри. В отличие от обычных определений функций C, их значение может захватывать состояние из окружающего их контекста. Определение блока создает непрозрачное значение, которое содержит как ссылку на код внутри блока, так и снимок текущего состояния локальных переменных стека на момент его определения. Блок может быть позже вызван так же, как указатель функции. Блок может быть назначен переменным, передан функциям и иным образом обработан как обычный указатель на функцию, хотя прикладной программист (или API) должен пометить блок специальным оператором (Block_copy), если он будет использоваться вне области видимости в который был определен.
Учитывая значение блока, код внутри блока может быть выполнен в любое более позднее время путем его вызова с использованием того же синтаксиса, который использовался бы для вызова функции.
Простым примером захвата изменяемого состояния в окружающей области является целочисленный диапазон iterator :
/ * blocks-test.c * / #include#include / * Тип блока, который ничего не возвращает int * / typedef int (^ IntBlock) (); IntBlock MakeCounter (int start, int increment) {__block int i = start; return Block_copy (^ (void) {int ret = i; i + = приращение; return ret;}); } int main (void) {IntBlock mycounter = MakeCounter (5, 2); printf ("Первый вызов:% d \ n", mycounter ()); printf ("Второй вызов:% d \ n", mycounter ()); printf ("Третий вызов:% d \ n", mycounter ()); / * поскольку он был скопирован, его также необходимо освободить * / Block_release (mycounter); возврат 0; }
$ clang -fblocks blocks-test.c # Mac OS X $./a.out Первый вызов: 5 Второй вызов: 7 Третий вызов: 9
Среда выполнения блоков не является частью библиотек C, связанных по умолчанию в некоторых системах. В этом случае требуется явная ссылка на эту библиотеку:
$ clang -fblocks blocks-test.c -lBlocksRuntime # Linux
Среда выполнения является частью среды выполнения clang, но иногда не устанавливается с пакет clang. Доступна автономная среда выполнения, извлеченная из compiler-rt.
Блоки имеют внешнее сходство с расширением C GCC для поддержки лексически ограниченная вложенные функции. Однако вложенные функции GCC, в отличие от блоков, не должны вызываться после выхода из содержащей их области, так как это приведет к неопределенному поведению.
вложенные функции в стиле GCC в настоящее время используют динамическое создание исполняемых переходов на большинстве архитектур при получении адреса вложенной функции. На большинстве архитектур (включая X86) эти переходники создаются в стеке, что требует пометки исполняемого файла стека. Исполняемые стеки обычно считаются потенциальной дырой в безопасности. Блоки не требуют использования исполняемых преобразователей, поэтому они не разделяют эту слабость. С другой стороны, блоки представляют собой совершенно новый тип указателя, тогда как указатели на вложенные функции в GCC являются обычными указателями на функции и могут использоваться непосредственно с существующим кодом.