C 扩展对闭包特性的支持
今日听说某君批评 C 语言说它【输入一个参数返回一个函数】很困难。
例如在 Python 中,你可以
def addn(n):
def addx(x):
return n + x
return addx
my_adder = addn(42)
print(my_adder(21))
标准 C 要实现这样的功能也不是不可以,这是一个闭包的功能,我们只要显式的把上下文抓住就可以了。
#include <stdio.h>
typedef struct Adder { int n; } Adder;
Adder addn(int n) {
Adder addn;
addn.n = n;
return addn;
}
int apply(Adder addn, int x) { return addn.n + x; }
int main() {
Adder add42 = addn(42);
printf("%d\n", apply(add42, 21));
return 0;
}
这样的写法未免过于复杂,而闭包是现代程序设计里面很常用到的一种结构,面对更复杂的上下文,为了模拟闭包,所要做的比一个 Adder 结构体要多得多。对于这样常用的结构,主流的 C 编译器,即 gcc 和 clang 都提供了 C 扩展来支持这样的功能。
在 clang 中,你可以这样写
#include <stdio.h>
#include <Block.h>
int (^addn(int n))(int) {
__block int i = n;
return Block_copy( ^(int x) {
return x + n;
});
}
int main() {
int (^add42)(int) = addn(42);
printf("%d\n", add42(21));
return 0;
}
熟悉 Objective-C 的同学应该对 block 不陌生,这里 block 的类型名写起来比较麻烦,可以用 typedef int (^MyClosure)(int); 来定义更有可读性的类型名。
在 gcc 中,可以使用 nested functions 扩展
#include <stdio.h>
int (*addn(int n))(int) {
int addx(int x) {
return n + x;
}
return addx;
}
int main() {
int (*add42)(int) = addn(42);
printf("%d\n", add42(21));
return 0;
}
同样这里的函数指针也可以用 typedef 来定义一个可读的类型名。
这个问题在 C++ 中可以通过在类中重载括号运算符来实现。本质上是上面复杂代码所揭示出的捕获上下文并查看上下文信息的动作,现代语言为此封装了看起来像直接调用的简洁语法,使得代码更好写,更好读。
C 扩展对闭包特性的支持的更多相关文章
- 目前主流编译器对C++11特性的支持情况
目前主流编译器对C++11特性的支持情况 1. GCC编译器(从编译器GCC4.8.X的版本完全支持) (1)目前C++11特性,之前成为C++0X特性,从GCC4.3的后续版本中逐步对C++11进行 ...
- 深入理解JavaScript的闭包特性如何给循环中的对象添加事件
初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...
- 快速入门系列--WCF--08扩展与新特性
最后一章将进行WCF扩展和新特性的学习,这部分内容有一定深度,有一个基本的了解即可,当需要自定义一个完整的SOA框架时,可以再进行细致的学习和实践. 服务端架构体系的构建主要包含接下来的几个要素:服务 ...
- Datagrid扩展方法onClickCell{easyui-datagrid-扩充-支持单元格编辑}
//-----------------------------------------------------------------/******************************** ...
- 如何给循环中的对象添加事件--深入理解JavaScript的闭包特性
初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...
- 深入理解JavaScript的闭包特性 如何给循环中的对象添加事件(转载)
原文参考:http://blog.csdn.net/gaoshanwudi/article/details/7355794 初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数 ...
- JavaScript的闭包特性
闭包是一个比较抽象的概念,尤其是对js新手来说.在这里,我就我个人的理解j简单谈一下: 闭包:官方解释是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部 ...
- 从匿名函数(闭包特性)到 PHP 设计模式之容器模式
匿名函数(匿名函数) 匿名函数,也叫闭包函数,它允许临时创建一个没有指定名称的函数,常用作回调函数参数的值,也可以作为变量的值来使用.具体的使用见以下示例代码: /* 示例一:声明一个简单匿名函数,并 ...
- JavaScript快速检测浏览器对CSS3特性的支持情况
项目中使用动画效果在IE9下不支持,所以写了个判断浏览器是否支持动画的函数,进而扩展到下面判断浏览器支持任一特定CSS3属性的函数. function supportAnimation(){ var ...
随机推荐
- CF803D 题解
题面 正解:一道二分大水题! A:为什么我得不到满分? B : 评测的系统不一样啊! A : 蛤? 正常情况下我们日常练习均使用的是windows系统,在windows下,string 本身是可以存储 ...
- 【JDK】JDK源码分析-TreeMap(1)
概述 前面数据结构与算法笔记对红黑树进行了分析,而 TreeMap 内部就是基于红黑树实现的.示意图: 它的查找.插入.删除操作的时间复杂度均为 O(logn). TreeMap 类的继承结构如下: ...
- 【Android Studio】常用快捷键
1. 删除一行:Ctrl + X 更新中……
- 【iOS】copy 关键字
以前没注意过 iOS 的 copy, nonatomic, assign, weak, strong 等关键字. 偏偏今天遇到了一个问题,恰恰是关键字的问题,如图: 之前用的是 assign, 没有用 ...
- 关于STM32GPIO按键上下拉配置的认识
说真的,后知后觉这个问题还是有点值得研究的,一开始学习我用的板子在按键模块电路中GPIO输入脚是有外部上下拉电阻的,如下图所示:当KEY1接V3.3,在其后为它接一个下拉电阻,可以保证按下按键输入高电 ...
- 如何确定FPGA电路中DDR4的Speed bin 是否兼容?
原创 by DeeZeng DDR4 是否兼容,拿更快速度的DDR4,是否可以不改FPGA工程,直接换料就能直接用? 实际工作中,经常会碰到因为DDR3/4 或其他料件换料了,需要判断FPGA工程中I ...
- 解释一下一门语言该有的东东(Javascript)
注释 Js中有两种注释 // 单行注释 /**/ 多行注释 变量 变量就像学校学习的 未知数 如 3 + x = 8 x: 类似变量,在改造一下 x + y = z 当 x=3, y=5, z=8, ...
- zabbix监控WEB网站性能
一直在纠结用什么实例来给大家演示呢?想来想去还是官方的好,那我们怎么用zabbix监控web性能和可用性呢?我们这边分为几个步骤:打开网站.登陆.登陆验证.退出,一共4个小step,看实例. 检测流程 ...
- Windows 纠错
4:在Windows应用程序中,当需要将窗体显示为模式对话框时,需要调用窗体的()方法.(选择一项)A:Activate()B:ShowDialog()C:Show()D:Close()正确答案是 B ...
- python基础之循环与迭代器
循环 python 循环语句有for循环和while循环. while循环while循环语法 while 判断条件: 语句 #while循环示例 i = 0 while i < 10: i += ...