这个 C 代码怎么会有 lambda

Posted

技术标签:

【中文标题】这个 C 代码怎么会有 lambda【英文标题】:How can this C code have lambda 【发布时间】:2022-01-09 10:33:27 【问题描述】:

这段代码:

#include <stdio.h>

int main()

    void (^a)(void) = ^ void ()  printf("test");  ;
    a();

使用 clang -Weverything -pedantic -std=c89(版本 clang-800.0.42.1)在没有警告的情况下编译并打印 test

我找不到任何有关具有 lambda 的标准 C 的信息,gcc 也有它自己的 lambda 语法,如果存在标准解决方案,他们这样做会很奇怪。

【问题讨论】:

无法在 Ubuntu 16.04 上使用 clang version 3.8.0-2ubuntu4 进行复制。失败:error: blocks support disabled - compile with -fblocks or pick a deployment target that supports them. 块是clang extension。 C 不能有这个代码。编译器特定的东西。 嗯,闻起来像 Objective-C。 你会认为-pedantic-std=c89 至少会对这个非标准代码产生警告! 【参考方案1】:

这种行为似乎特定于新版本的 Clang,并且是 language extension called "blocks"。

Wikipedia article on C "blocks" 也提供了支持这一说法的信息:

Block 是 Apple Inc. 添加到 Clang 的 C、C++ 和 Objective-C 编程语言实现的非标准扩展,它使用类似于 lambda 表达式的语法在这些语言中创建闭包语言。为 Mac OS X 10.6+ 和 ios 4.0+ 开发的程序支持块,但第三方运行时允许在 Mac OS X 10.5 和 iOS 2.2+ 以及非 Apple 系统上使用。

以上重点是我的。在Clang's language extension page, under the "Block type" section 上,它简要概述了 Block 类型是什么:

与函数类型一样,块类型是由结果值类型和参数类型列表组成的对,与函数类型非常相似。块的用途很像函数,主要区别在于除了可执行代码之外,它们还包含与自动(堆栈)或托管(堆)内存的各种变量绑定。

GCC 也有一些类似于块的东西,称为词法范围嵌套函数。但是,在有关 C 块的 Wikipedia 文章中也有一些关键差异:

块与 GCC 对 C 的扩展以支持词法范围的嵌套函数有表面上的相似之处。但是,与块不同,GCC 的嵌套函数不能在包含范围退出后调用,因为那样会导致未定义的行为。

GCC 样式的嵌套函数在获取嵌套函数的地址时也需要动态创建可执行的 thunk。 [...]。

以上重点是我的。

【讨论】:

【参考方案2】:

C 标准根本没有定义 lambda,但实现可以添加扩展。

Gcc 还添加了一个扩展,以便支持具有静态作用域的 lambda 的编程语言能够轻松地将它们转换为 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;

【讨论】:

代码用-std=c89 -pedantic编译,不应该是语言扩展 @mantal 仅仅因为在使用-std=c89 -pedantic 编译时clang 不报告任何诊断并不意味着“它不应该是语言扩展”。可能是,clang 的 -std=c89 -pedantic 无法识别所有扩展或您使用的特定版本包含错误。 C 标准根本不支持 lamdas。

以上是关于这个 C 代码怎么会有 lambda的主要内容,如果未能解决你的问题,请参考以下文章

求一个符号怎么打,看图

C/C++程序中怎么会有静态地址?

C/C++程序中怎么会有静态地址?

Malloc 函数可以申请任意大小的堆区内存,如果 malloc(0) 会怎么样啊?这个代码好像也没有报错。

keil没有弹出是不是添加启动代码到该工程怎么办

如何在Unix 下运行c语言?