block的实质

以一个简单的实现为列子;

- (void)myBlcokTest{
void (^blk)()=^{
printf(@“beijinghuanyingni”);
};
blk();
}

终端:clang -rewrite-objc 类文件名.m

cpp文件中关键代码:

    static void _I_People_myBlcokTest(People * self, SEL _cmd) {
void (*blk)()=((void (*)())&__People__myBlcokTest_block_impl_0((void *)__People__myBlcokTest_block_func_0, &__People__myBlcokTest_block_desc_0_DATA));
((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk); } static void __People__myBlcokTest_block_func_0(struct __People__myBlcokTest_block_impl_0 *__cself) {
printf("woshinidexiaodaye");
} struct __People__myBlcokTest_block_impl_0 {
struct __block_impl impl;
struct __People__myBlcokTest_block_desc_0* Desc;
__People__myBlcokTest_block_impl_0(void *fp, struct __People__myBlcokTest_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
}; // 第一个成员
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
// 第二个成员
static struct __People__myBlcokTest_block_desc_0 {
size_t reserved;// 升级版本所需要的区域
size_t Block_size;//block大小
} __People__myBlcokTest_block_desc_0_DATA = { 0, sizeof(struct __People__myBlcokTest_block_impl_0)};

运行时的myBlcokTest方法;

 static void _I_People_myBlcokTest(People * self, SEL _cmd) {

        void (*blk)()=((void (*)())&__People__myBlcokTest_block_impl_0((void *)__People__myBlcokTest_block_func_0, &__People__myBlcokTest_block_desc_0_DATA));

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

 }

去掉类型转化

static void _I_People_myBlcokTest(People * self, SEL _cmd) {
__People__myBlcokTest_block_impl_0 blk = __People__myBlcokTest_block_impl_0( __People__myBlcokTest_block_func_0, &__People__myBlcokTest_block_desc_0_DATA)); 、、、
}

__People__myBlcokTest_block_impl_0:是一个结构体 包含两个成员:

struct __block_impl impl;
struct __People__myBlcokTest_block_desc_0* Desc;

以及一个构造函数:
__People__myBlcokTest_block_impl_0(void *fp, struct __People__myBlcokTest_block_desc_0 *desc, int flags=0) 
struct __People__myBlcokTest_block_impl_0 {
成员一: struct __block_impl impl; // __block_impl结构体
                  struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
     成员二:     struct __People__myBlcokTest_block_desc_0* Desc;//__People__myBlcokTest_block_desc_0结构体
                        static struct __People__myBlcokTest_block_desc_0 {
size_t reserved;// 升级版本所需要的区域
size_t Block_size;//block大小
}

  构造函数:
          构造函数中成员的处理 在后面 构造函数中参数的处理部分解释;
__People__myBlcokTest_block_impl_0(void *fp, struct __People__myBlcokTest_block_desc_0 *desc, int flags=0)
{
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};

通过结构体的构造函数生成一个block实例

 __People__myBlcokTest_block_impl_0 blk = __People__myBlcokTest_block_impl_0( __People__myBlcokTest_block_func_0,
&__People__myBlcokTest_block_desc_0_DATA));  构造函数参数的意义:
参数一:    __People__myBlcokTest_block_func_0  //函数实现地址  在把函数赋值给函数指针的时候可以省略&;
在构造函数参数的意义: 把函数的地址赋值给指针 void *fp
函数的具体实现代码:
static void __People__myBlcokTest_block_func_0(struct __People__myBlcokTest_block_impl_0 *__cself) {
printf("woshinidexiaodaye");
}
这里面的__cself是什么后面会解释;
参数二: &__People__myBlcokTest_block_desc_0_DATA // __People__myBlcokTest_block_desc_0的默认初始化
{ 0, sizeof(struct __People__myBlcokTest_block_impl_0) //使用__People__myBlcokTest_block_impl_0的大小进行初始化
具体代码:
static struct __People__myBlcokTest_block_desc_0 {
size_t reserved;// 升级版本所需要的区域
size_t Block_size;//block大小
} __People__myBlcokTest_block_desc_0_DATA = { 0, sizeof(struct __People__myBlcokTest_block_impl_0)};

函数指针 与指针函数点击这里

构造函数中参数的处理

 __People__myBlcokTest_block_impl_0(void *fp, struct __People__myBlcokTest_block_desc_0 *desc, int flags=0)
{
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
赋值之后:
__People__myBlcokTest_block_impl_0(void *fp, struct __People__myBlcokTest_block_desc_0 *desc, int flags=0)
{
impl.isa = &_NSConcreteStackBlock;//_NSConcreteStackBlock用于初始化isa成员 后面具体解释
                impl.Flags = 0;
impl.FuncPtr =__People__myBlcokTest_block_func_0;
imlp.Reserved=0;
                Desc =__People__myBlcokTest_block_desc_0_DATA;
            }

再来看看block的调用:

blk();

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

简化

 ((__block_impl *)blk)->FuncPtr)((__block_impl *)blk); =>(blk ->FuncPtr)(blk)

获取blk结构体中函数指针FuncPtr 通过该函数指针调用函数 并且参数值为blk   点击这里

这个等价于

(blk ->FuncPtr)(blk) 相当于

blk -> __People__myBlcokTest_block_func_0(blk);

再看看

static void __People__myBlcokTest_block_func_0(struct __People__myBlcokTest_block_impl_0 *__cself) {
printf("woshinidexiaodaye");
}

说明 __cself 就是blk 本身;

傻瓜学编程之block_2的更多相关文章

  1. 傻瓜学编程之block_3

    block 捕获自动变量的瞬间值: 注释在代码中:请参考傻瓜学编程之block_3 import "People.h" @interface People() { int your ...

  2. 傻瓜学编程之block_1

    1.引出 1.1.int pp = 3;for循环为dd赋值并 调用 finprint(int ,int)函数 获取pp*dd的乘积,输出 void finalValue(int d, int sca ...

  3. C#可扩展编程之MEF学习笔记(五):MEF高级进阶

    好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...

  4. 2017“编程之美”终章:AI之战勇者为王

    编者按:8月15日,第六届微软“编程之美”挑战赛在选手的火热比拼中圆满落下帷幕.“编程之美”挑战赛是由微软主办,面向高校学生开展的大型编程比赛.自2012年起,微软每年都在革新比赛命题.紧跟时代潮流, ...

  5. 网络编程之TCP/IP各层详解

    网络编程之TCP/IP各层详解 我们将应用层,表示层,会话层并作应用层,从TCP/IP五层协议的角度来阐述每层的由来与功能,搞清楚了每层的主要协议,就理解了整个物联网通信的原理. 首先,用户感知到的只 ...

  6. Python Flask高级编程之RESTFul API前后端分离精讲 (网盘免费分享)

    Python Flask高级编程之RESTFul API前后端分离精讲 (免费分享)  点击链接或搜索QQ号直接加群获取其它资料: 链接:https://pan.baidu.com/s/12eKrJK ...

  7. Python网络编程之TCP套接字简单用法示例

    Python网络编程之TCP套接字简单用法示例 本文实例讲述了Python网络编程之TCP套接字简单用法.分享给大家供大家参考,具体如下: 上学期学的计算机网络,因为之前还未学习python,而jav ...

  8. Python Flask高级编程之从0到1开发《鱼书》精品项目

    Python Flask高级编程之从0到1开发<鱼书>精品项目     整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感 ...

  9. Java并发编程之CAS二源码追根溯源

    Java并发编程之CAS二源码追根溯源 在上一篇文章中,我们知道了什么是CAS以及CAS的执行流程,在本篇文章中,我们将跟着源码一步一步的查看CAS最底层实现原理. 本篇是<凯哥(凯哥Java: ...

随机推荐

  1. 3.9 run_main.py源码(兼容python2和3)

    3.9 run_main.py源码(兼容python2和3) 以下代码在python2和python3上都跑通过,python3只需注释掉上面红色框框区域代码就行(最后一步发送邮箱代码,我注释掉了). ...

  2. spark学习笔记_1

    简单的讲,Apache Spark是一个快速且通用的集群计算系统. Apache Spark 历史: 2009年由加州伯克利大学的AMP实验室开发,并在2010年开源,13年时成长为Apache旗下大 ...

  3. Python学习之路基础篇--09Python基础,初识函数

    函数可以分为内置函数 和 自定义函数.这次关注的主要是自定义函数.定义函数之后,就可以在任何需要它的地方调用. 1 返回值的重要性 返回值的3种情况 没有返回值 ---- 返回None 不定 retu ...

  4. Python全栈之路----常用模块----hashlib加密模块

    加密算法介绍 HASH       Python全栈之路----hash函数 Hash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列 ...

  5. SSH与MVC

    MVC是一个框架模式,它强制性的使应用程序的输入.处理和输出分开.使用MVC应用程序被分成三个核心部件:模型.视图.控制器.它们各自处理自己的任务.最典型的MVC就是JSP + servlet + j ...

  6. SERvet的表单

    首先要建立好数据库. 好了,先写好两个静态页面,分别负责登录和注册. 代码清单1:login.jsp(登录页面) <%-- Document : login Created on : 2013- ...

  7. Qt学习2---信号与槽

    connect(&b1,&QPushButton::pressed,this,&MainWidget::close); &b1:信号发出者,指针类型 &QPus ...

  8. myEclipse出现cannot paste the clipboard contents into the selected elements报错

    导入jar包报错,cannot paste the clipboard contents into the selected elements,查阅资料让重新打开工程,但依然报错. 最后在本地路径复制 ...

  9. UT源码 105032014098

    package exam1; import java.util.Scanner; public class test01 { static String nextDate(int year,int m ...

  10. vue2上传图片到OSS

    第一步:安装阿里云OSS <!-- 引入在线资源 --> <script src="http://gosspublic.alicdn.com/aliyun-oss-sdk- ...