这个 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的主要内容,如果未能解决你的问题,请参考以下文章