#objective-c #linux #macos #syntax
#c #лямбда
Вопрос:
Этот код:
#include <stdio.h>
int main()
{
void (^a)(void) = ^ void () { printf("test"); } ;
a();
}
Скомпилируйте без предупреждения с помощью clang -Weverything -pedantic -std=c89 (версия clang-800.0.42.1) и распечатайте test
.
Я не смог найти никакой информации о стандартном C, имеющем lambda, также gcc имеет свой собственный синтаксис для lambda, и было бы странно, если бы они делали это, если бы существовало стандартное решение.
Комментарии:
1. Не удается воспроизвести
clang version 3.8.0-2ubuntu4
в Ubuntu 16.04. Сбой с помощью:error: blocks support disabled - compile with -fblocks or pick a deployment target that supports them
.2. Блоки — это расширение clang .
3. C не может иметь этот код. Что-то специфичное для компилятора.
4. Мммм, это пахнет как Objective-C.
5. Можно подумать
-pedantic
, что with-std=c89
, по крайней мере, выдаст предупреждение для этого нестандартного кода!
Ответ №1:
Такое поведение, по-видимому, характерно для более новых версий Clang и является расширением языка, называемым «блоки».
Статья Википедии о «блоках» C также предоставляет информацию, подтверждающую это утверждение:
Блоки — это нестандартное расширение, добавленное Apple Inc. к реализациям Clang языков программирования C, C и Objective-C, которое использует синтаксис, подобный лямбда-выражению, для создания замыканий в этих языках. Блоки поддерживаются для программ, разработанных для Mac OS X 10.6 и iOS 4.0 , хотя среды выполнения сторонних производителей позволяют использовать их в Mac OS X 10.5 и iOS 2.2 и системах, отличных от Apple.
Акцент выше мой. На странице расширения языка Clang в разделе «Тип блока» дается краткий обзор типа блока:
Как и типы функций, тип блока представляет собой пару, состоящую из типа результирующего значения и списка типов параметров, очень похожих на тип функции. Блоки предназначены для использования так же, как функции, с ключевым отличием в том, что в дополнение к исполняемому коду они также содержат различные привязки переменных к автоматической (стековой) или управляемой (кучной) памяти.
GCC также имеет нечто похожее на блоки, называемые вложенными функциями с лексической областью действия. Однако в статьях Википедии о блоках C также отмечены некоторые ключевые различия:
Блоки имеют поверхностное сходство с расширением C GCC для поддержки вложенных функций с лексической областью действия.Однако вложенные функции GCC, в отличие от блоков, не должны вызываться после выхода из содержащей области, поскольку это приведет к неопределенному поведению.
Вложенные функции в стиле GCC также требуют динамического создания исполняемых файлов при получении адреса вложенной функции. […].
Акцент выше мой.
Ответ №2:
стандарт C вообще не определяет лямбды, но реализации могут добавлять расширения.
Gcc также добавил расширение, чтобы языки программирования, поддерживающие лямбды со статической областью видимости, могли легко преобразовывать их в C и напрямую компилировать замыкания.
Вот пример расширения gcc, который реализует замыкания.
#include <stdio.h>
int(*mk_counter(int x))(void)
{
int inside(void) {
return x;
}
return inside;
}
int
main() {
int (*counter)(void)=mk_counter(1);
int x;
x=counter();
x=counter();
x=counter();
printf("%dn", x);
return 0;
}
Комментарии:
1. Код компилируется с помощью -std=c89 -педантично, он не должен быть расширением языка
2. @mantal То, что clang не сообщает о какой-либо диагностике при компиляции с
-std=c89 -pedantic
помощью, не означает, что «Это не должно быть расширением языка». Может быть, clang-std=c89 -pedantic
не объединяет все расширения или конкретная версия, которую вы используете, содержит ошибку. Стандарт C просто не поддерживает lamda.