2017-01-17 2 views
4

Этот код:Как это C-код может иметь Лямбда

#include <stdio.h> 

int main() 
{ 
    void (^a)(void) =^void() { printf("test"); } ; 
    a(); 
} 

Compile без предупреждения с лязгом -Weverything -pedantic -std = c89 (версия лязг-800.0.42.1) и печать test.

Я не мог найти информацию о стандарте C, имеющем лямбда, а также gcc имеет собственный синтаксис для лямбда, и было бы странно, если бы они сделали это, если бы существовало стандартное решение.

+0

Невозможно воспроизвести с 'clang version 3.8.0-2ubuntu4' на Ubuntu 16.04. Сбой: ошибка: блокировка поддержки отключена - скомпилируйте с -fblocks или выберите цель развертывания, которая их поддерживает. – usr

+3

Блоки - это расширение [clang extension] (http://clang.llvm.org/docs/BlockLanguageSpec.html). – StoryTeller

+3

C не может иметь этот код. Что-то компилятор специфичен. –

ответ

2

Это поведение, по-видимому, зависит от новых версий Clang и является language extension called "blocks".

Wikipedia article on C "blocks" также предоставляет информацию, которая поддерживает это утверждение:

Blocks are a non-standard extension added by Apple Inc. to Clang's implementations of the C, C++, and Objective-C programming languages that uses a lambda expression-like syntax to create closures within these languages. Blocks are supported for programs developed for Mac OS X 10.6+ and iOS 4.0+, although third-party runtimes allow use on Mac OS X 10.5 and iOS 2.2+ and non-Apple systems.

Акцент выше мой. На Clang's language extension page, under the "Block type" section, это дает краткий обзор того, что тип блока:

Like function types, the Block type is a pair consisting of a result value type and a list of parameter types very similar to a function type. Blocks are intended to be used much like functions with the key distinction being that in addition to executable code they also contain various variable bindings to automatic (stack) or managed (heap) memory.

GCC также есть что-то похожее на блоки, называемые лексически ограниченные вложенные функции. Тем не менее, есть некоторые ключевые различия, также отмеченные в статьях Википедии о блоках С:

Blocks bear a superficial resemblance to GCC's extension of C to support lexically scoped nested functions. However, GCC's nested functions, unlike blocks, must not be called after the containing scope has exited, as that would result in undefined behavior.

GCC-style nested functions also require dynamic creation of executable thunks when taking the address of the nested function. [...].

Упор выше, мой.

2

стандарт C не определяет lambdas вообще, но реализации могут добавлять расширения.

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("%d\n", x); 
    return 0; 
} 
+0

Код компиляции с -std = c89 -pedantic, не должен быть расширением языка – mantal

+1

@mantal Просто потому, что clang не сообщает о какой-либо диагностике при компиляции с помощью '-std = c89 -pedantic' не означает« Это не должно быть языковым расширением ». Может быть, clang's -std = c89 -pedantic' не восстанавливает все расширения или конкретная версия, которую вы используете, содержит ошибку. Стандарт C просто не поддерживает lamdas. – usr

Смежные вопросы