免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: davelv
打印 上一主题 下一主题

C语言对闭包运算的支持 [复制链接]

论坛徽章:
0
31 [报告]
发表于 2011-12-02 13:39 |只看该作者
本帖最后由 tony_ayuan 于 2011-12-02 13:42 编辑

回复 27# davelv

ok,函数的存储位置我猜错了。

我还是坚持这不是闭包,更不是lamda。

nested_func的参数传递与普通的(顶层翻译单元)函数是一样的。

与普通函数最大的不同就是nested_func具有访问外围函数局部变量的能力,这些局部变量存储在调用栈上。  

另外一点不同是编译后的函数名。

第1点是不能在外围函数之外直接调用nested_func的原因。
第2点是防止直接调用nested_func的机制。

下面的例子,函数a,b,e,f说明参数传递方式。函数main,q说明访问外围函数局部变量的方式。

  1. int a(void)      
  2. {
  3.   return 1;
  4. }

  5. int e(int x)
  6. {
  7.   return x++;
  8. }

  9. int main(void)
  10. {
  11.   int foo1 = 1;
  12.   int foo2 = 2;
  13.   int foo3 = 3;

  14.   int b(void)
  15.   {
  16.     return 1;
  17.   }

  18.   int f(int x)
  19.   {
  20.     return x++;
  21.   }

  22.   int q(void)
  23.   {
  24.     foo1++;
  25.     foo3++;
  26.     return 0;
  27.   }

  28.   foo2++;

  29.   a();
  30.   b();
  31.   e(1);
  32.   f(1);
  33.   q();

  34.   return 0;
  35. }
复制代码

  1. 0000000000400494 <a>:
  2.   400494:       55                      push   %rbp
  3.   400495:       48 89 e5                mov    %rsp,%rbp
  4.   400498:       b8 01 00 00 00          mov    $0x1,%eax
  5.   40049d:       c9                      leaveq
  6.   40049e:       c3                      retq   

  7. 000000000040049f <e>:
  8.   40049f:       55                      push   %rbp
  9.   4004a0:       48 89 e5                mov    %rsp,%rbp
  10.   4004a3:       89 7d fc                mov    %edi,-0x4(%rbp)
  11.   4004a6:       8b 45 fc                mov    -0x4(%rbp),%eax
  12.   4004a9:       83 45 fc 01             addl   $0x1,-0x4(%rbp)
  13.   4004ad:       c9                      leaveq
  14.   4004ae:       c3                      retq   

  15. 00000000004004af <b.1602>:
  16.   4004af:       55                      push   %rbp
  17.   4004b0:       48 89 e5                mov    %rsp,%rbp
  18.   4004b3:       b8 01 00 00 00          mov    $0x1,%eax
  19.   4004b8:       c9                      leaveq
  20.   4004b9:       c3                      retq   

  21. 00000000004004ba <main>:
  22.   4004ba:       55                      push   %rbp
  23.   4004bb:       48 89 e5                mov    %rsp,%rbp
  24.   4004be:       48 83 ec 10             sub    $0x10,%rsp
  25.   4004c2:       c7 45 f4 01 00 00 00    movl   $0x1,-0xc(%rbp)
  26.   4004c9:       c7 45 fc 02 00 00 00    movl   $0x2,-0x4(%rbp)
  27.   4004d0:       c7 45 f0 03 00 00 00    movl   $0x3,-0x10(%rbp)
  28.   4004d7:       83 45 fc 01             addl   $0x1,-0x4(%rbp)
  29.   4004db:       e8 b4 ff ff ff          callq  400494 <a>
  30.   4004e0:       e8 ca ff ff ff          callq  4004af <b.1602>
  31.   4004e5:       bf 01 00 00 00          mov    $0x1,%edi
  32.   4004ea:       e8 b0 ff ff ff          callq  40049f <e>
  33.   4004ef:       bf 01 00 00 00          mov    $0x1,%edi
  34.   4004f4:       e8 13 00 00 00          callq  40050c <f.1605>
  35.   4004f9:       48 8d 45 f0             lea    -0x10(%rbp),%rax
  36.   4004fd:       49 89 c2                mov    %rax,%r10
  37.   400500:       e8 17 00 00 00          callq  40051c <q.1608>
  38.   400505:       b8 00 00 00 00          mov    $0x0,%eax
  39.   40050a:       c9                      leaveq
  40.   40050b:       c3                      retq   

  41. 000000000040050c <f.1605>:
  42.   40050c:       55                      push   %rbp
  43.   40050d:       48 89 e5                mov    %rsp,%rbp
  44.   400510:       89 7d fc                mov    %edi,-0x4(%rbp)
  45.   400513:       8b 45 fc                mov    -0x4(%rbp),%eax
  46.   400516:       83 45 fc 01             addl   $0x1,-0x4(%rbp)
  47.   40051a:       c9                      leaveq
  48.   40051b:       c3                      retq   

  49. 000000000040051c <q.1608>:
  50.   40051c:       55                      push   %rbp
  51.   40051d:       48 89 e5                mov    %rsp,%rbp
  52.   400520:       4c 89 d0                mov    %r10,%rax
  53.   400523:       8b 50 04                mov    0x4(%rax),%edx
  54.   400526:       83 c2 01                add    $0x1,%edx
  55.   400529:       89 50 04                mov    %edx,0x4(%rax)
  56.   40052c:       8b 10                   mov    (%rax),%edx
  57.   40052e:       83 c2 01                add    $0x1,%edx
  58.   400531:       89 10                   mov    %edx,(%rax)
  59.   400533:       b8 00 00 00 00          mov    $0x0,%eax
  60.   400538:       c9                      leaveq
  61.   400539:       c3                      retq   
  62.   40053a:       90                      nop
  63.   40053b:       90                      nop
  64.   40053c:       90                      nop
  65.   40053d:       90                      nop
  66.   40053e:       90                      nop
  67.   40053f:       90                      nop
复制代码

论坛徽章:
0
32 [报告]
发表于 2011-12-02 13:52 |只看该作者
回复 33# tony_ayuan
对语言的使用者来说,语言特性如何实现的很重要么?
或者像这种,C语言没有在语法上支持类,就不能用C写出面向对象的程序?

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
33 [报告]
发表于 2011-12-02 14:36 |只看该作者
回复  davelv

nested_func的参数传递与普通的(顶层翻译单元)函数是一样的。
tony_ayuan 发表于 2011-12-02 13:39


在lz一开始的例子里, 传递机制不一样。
有个局部的 i 是通过一个隐藏的 ecx 传入其地址的。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
34 [报告]
发表于 2011-12-02 14:38 |只看该作者
回复 30# fallening

回复 26# 幻の上帝


真的歪了, 各种意义上……
我觉得这只能算匿名函数, 没有包进非局部的什么东西

论坛徽章:
0
35 [报告]
发表于 2011-12-02 14:53 |只看该作者
回复  KanonInD

就是说受限于upvalue(内嵌函数使用的外部函数局域变量)的作用域。

你这个例子没什 ...
davelv 发表于 2011-12-02 12:56



    所以说,Nested Function就算是闭包,也是残废的闭包。

论坛徽章:
0
36 [报告]
发表于 2011-12-02 15:56 |只看该作者
本帖最后由 fallening 于 2011-12-02 15:57 编辑

回复 36# OwnWaterloo
我觉得是创建了一个匿名的类型并为之具现了一个实例。

取决于各自的理解吧,结合下边这个更明显的例子
  1.     auto p = new auto([]{});
复制代码
说是一个类型也不为过

论坛徽章:
0
37 [报告]
发表于 2011-12-02 17:50 |只看该作者
回复 34# davelv


能写出来。更像是用C实现了一种新语言

论坛徽章:
0
38 [报告]
发表于 2011-12-02 21:22 |只看该作者
闭包看上去至少要像这样:

  1. f := [:x | [:y :z | (x+y)*z.]].
  2. g := f value: 100.
  3. h := f value: 5.
  4. (g value: 200 value: 6) printNl.
  5. (h value: 10 value: 5) printNl.
复制代码

论坛徽章:
0
39 [报告]
发表于 2011-12-03 00:43 |只看该作者
回复 40# KanonInD

残废也罢,单线程下就这么凑合着用吧。看起来不怎么顺眼呢
  1.         int (*f(int x))(int y,int z)
  2.         {   
  3.                 int n(int y, int z)
  4.                 {   
  5.                         return x+y+z;
  6.                 } ;
  7.                 return n;
  8.         }   
  9.         #define g f(2)
  10.         #define h f(3)
  11.         printf("%d,%d",g(2,2),h(2,2));
复制代码

论坛徽章:
0
40 [报告]
发表于 2011-12-03 00:46 |只看该作者
回复 39# tony_ayuan

如果什么东西都仅限于语法,语言的范围也太狭窄了。
话题跑偏了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP