Блоки (расширение языка C)
Блоки — это нестандартное расширение, добавленное Apple Inc. к языков реализациям Clang программирования C , C++ и Objective-C , которое использует синтаксис, подобный лямбда-выражению , для создания замыканий в этих языках. Блоки поддерживаются для программ, разработанных для Mac OS X 10.6+ и iOS 4.0+, [1] хотя сторонние среды выполнения позволяют использовать их в Mac OS X 10.5 и iOS 2.2+. [2] и системы сторонних производителей.
Apple разработала блоки с явной целью облегчить написание программ для архитектуры потоков Grand Central Dispatch . [3] [4] хотя он не зависит от этой архитектуры и может использоваться почти так же, как замыкания в других языках. Apple реализовала оба блока в своей собственной ветке коллекции компиляторов GNU. [1] и в исходном интерфейсе компилятора Clang LLVM . языка библиотеки времени выполнения Поддержка блоков также доступна как часть проекта LLVM. Группа Khronos использует синтаксис блоков для постановки ядер в очередь из ядер, начиная с версии 2.0 OpenCL . [5]
Как и определения функций, блоки могут принимать аргументы и объявлять свои собственные переменные внутри. В отличие от обычных определений функций C, их значение может фиксировать состояние из окружающего контекста. Определение блока создает непрозрачное значение, которое содержит как ссылку на код внутри блока, так и снимок текущего состояния локальных переменных стека на момент его определения. Блок может быть позже вызван таким же образом, как и указатель на функцию. Блок может быть назначен переменным, передан в функции или иным образом обработан как обычный указатель на функцию, хотя программист приложения (или API) должен пометить блок специальным оператором (Block_copy), если он будет использоваться вне области действия в которым это было определено.
Учитывая значение блока, код внутри блока может быть выполнен в любой момент позже, вызвав его, используя тот же синтаксис, который использовался бы для вызова функции.
Примеры
[ редактировать ]Простым примером фиксации изменяемого состояния в окружающей области является итератор целочисленного диапазона : [6]
/* blocks-test.c */
#include <stdio.h>
#include <Block.h>
/* Type of block taking nothing returning an int */
typedef int (^IntBlock)();
IntBlock MakeCounter(int start, int increment) {
__block int i = start;
return Block_copy( ^(void) {
int ret = i;
i += increment;
return ret;
});
}
int main(void) {
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;
}
Скомпилируйте и выполните
[ редактировать ]$ clang -fblocks blocks-test.c # Mac OS X
$ ./a.out
First call: 5
Second call: 7
Third call: 9
Среда выполнения блоков не является частью библиотек C, связанных по умолчанию в некоторых системах. Если это так, необходимо явно ссылаться на эту библиотеку:
$ clang -fblocks blocks-test.c -lBlocksRuntime # Linux
Среда выполнения является частью среды выполнения clang, но иногда не устанавливается вместе с пакетом clang. Доступна автономная среда выполнения, извлеченная из компилятора-rt. [7]
Связь с вложенными функциями GCC
[ редактировать ]Блоки имеют внешнее сходство с GCC расширением C с лексической областью видимости для поддержки вложенных функций . [8] Однако вложенные функции GCC, в отличие от блоков, не должны вызываться после выхода из содержащей их области, так как это приведет к неопределенному поведению .
Вложенные функции в стиле GCC в настоящее время используют динамическое создание исполняемых файлов на большинстве архитектур при получении адреса вложенной функции. В большинстве архитектур (включая X86) эти переходники создаются в стеке, что требует маркировки исполняемого файла стека. Стеки исполняемых файлов обычно считаются потенциальной дырой в безопасности. Блоки не требуют использования исполняемых преобразователей, поэтому у них нет этой слабости. С другой стороны, блоки представляют совершенно новый тип указателя, тогда как указатели на вложенные функции в GCC являются указателями на обычные функции и могут использоваться непосредственно с существующим кодом.
См. также
[ редактировать ]- Замыкание (информатика)
- Лексическая область видимости
- Лямбда (программирование)
- Стопка спагетти
- Thunk (функциональное программирование)
- XNU
- C++11 (включает «лямбда-выражения»)
Ссылки
[ редактировать ]- ^ Jump up to: а б «Темы программирования блоков» . Разработчик Apple . Apple Inc. Проверено 8 марта 2011 г.
- ^ «Архив кода Google — долгосрочное хранилище для хостинга проектов Google Code» .
- ^ «Grand Central Dispatch» (PDF) (краткое описание технологии). Яблоко . 03 сентября 2009 г. Архивировано из оригинала (PDF) 20 сентября 2009 г. Проверено 9 июня 2009 г.
- ^ Сиракузы, Джон (1 сентября 2009 г.). «Mac OS X 10.6 Snow Leopard: обзор Ars Technica: Блоки» . Арс Техника .
- ^ Мунши, Аафтаб, изд. (13 июля 2013 г.). «Спецификация OpenCL C. Версия 2.0. Версия документа 11» (PDF) . Рабочая группа Khronos OpenCL. п. 173. Архивировано из оригинала (PDF) 5 ноября 2013 г. Проверено 23 июля 2013 г.
- ^ Бенгтссон, Иоахим. «Программирование с использованием блоков C на устройствах Apple» . Архивировано из оригинала 15 ноября 2017 г. Проверено 17 сентября 2009 г.
- ^ «mackyle/blocksruntime: среда выполнения автономных блоков» . Проверено 15 января 2020 г. .
- ^ «Вложенные функции: использование коллекции компиляторов GNU (GCC)» .
Внешние ссылки
[ редактировать ]- «Расширения языка Clang: блоки» . Проект ЛЛВМ . Проверено 20 января 2013 г.
- " "compiler-rt "Библиотека времени выполнения"" . Проект ЛЛВМ . Проверено 20 января 2013 г.