设为首页 加入收藏

TOP

C语言中闭包的探究及比较(六)
2013-07-22 17:59:38 来源: 作者: 【 】 浏览:1405
Tags:言中 包的 探究 比较

 

  首先是block结构体的实现:

  [cpp]

  #ifndef BLOCK_IMPL

  #define BLOCK_IMPL

  struct__block_impl {

  void *isa;

  int Flags;

  int Reserved;

  void *FuncPtr;

  };

  // 省略部分代码

  #endif

  第一个成员isa指针用来表示该结构体的类型,使其仍然处于Cocoa的对象体系中,类似Python对象系统中的PyObject。

  第二、三个成员是标志位和保留位。

  第四个成员是对应的“匿名函数”,在这个例子中对应函数:

  [cpp]

  static void __main_block_func_0(struct__main_block_impl_0 *__cself) {

  inti = __cself->i; // bound by copy

  printf("%d\n", i);

  }

  函数__main_block_func_0引入了参数__cself,为struct __main_block_impl_0 *类型,从参数名称就可以看出它的功能类似于C++(www.cppentry.com)中的this指针或者Objective-C的self。

  而struct __main_block_impl_0的结构如下:

  [cpp]

  struct __main_block_impl_0 {

  struct __block_impl impl;

  struct __main_block_desc_0* Desc;

  int i;

  __main_block_impl_0(void*fp, struct__main_block_desc_0 *desc, int_i, intflags=0) : i(_i) {

  impl.isa = &_NSConcreteStackBlock;

  impl.Flags = flags;

  impl.FuncPtr = fp;

  Desc = desc;

  }

  };

  从__main_block_impl_0这个名称可以看出该结构体是为main函数中第零个block服务的,即示例代码中的blk;也可以猜到不同场景下的block对应的结构体不同,但本质上第一个成员一定是struct __block_impl impl,因为这个成员是block实现的基石。

  结构体__main_block_impl_0又引入了一个新的结构体,也是中间代码里最后一个结构体:

  [cpp]

  static struct __main_block_desc_0 {

  unsigned long reserved;

  unsigned long Block_size;

  } __main_block_desc_0_DATA = { 0, sizeof(struct__main_block_impl_0)};

  可以看出,这个描述性质的结构体包含的价值信息就是struct __main_block_impl_0的大小。

  最后剩下main函数对应的中间代码:

  [cpp]

  int main(intargc, constchar * argv[])

  {

  int i = 1024;

  void(*blk)(void) = (void(*)(void))&__main_block_impl_0((void*)__main_block_func_0, &__main_block_desc_0_DATA, i);

  ((void(*)(struct__block_impl *))((struct__block_impl *)blk)->FuncPtr)((struct__block_impl *)blk);

  return 0;

  }

  从main函数对应的中间代码可以看出执行block的本质就是以block结构体自身作为__cself参数,这里对应__main_block_impl_0,通过结构体成员FuncPtr函数指针调用对应的函数,这里对应__main_block_func_0。

  其中,局部变量i是以值传递的方式拷贝一份,作为__main_block_impl_0的构造函数的参数,并以初始化列表的形式赋值给其成员变量i。所以,基于这样的实现,不允许直接修改外部变量是合理的——因为按值传递根本改不到外部变量。

  4. 从实现上看如何修改外部变量(__block类型指示符)

  如果想要修改外部变量,则需要用__block来修饰:

  [cpp]

  int main(intargc, constchar * argv[])

  {

  __block int i = 1024;

  void(^blk)(void) = ^{ i = 0; printf("%d\n", i); };

  blk();

  return0;

  }

  此时再看中间代码,发现多了一个结构体:

  [cpp]

  struct __Block_byref_i_0 {

  void *__isa;

  __Block_byref_i_0 *__forwarding;

  int __flags;

  int __size;

  int i;

  };

              

首页 上一页 3 4 5 6 7 8 9 下一页 尾页 6/9/9
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C语言中的序列点和副作用 下一篇C语言复杂声明的本质与局限

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: