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. 停止node进程和查看react-native-cli

    taskkill /f /t /im node.exe which react-native

  2. spring cloud_1_mm_ribbon

    ji接上文 ribbon做请求分发负载均衡 ribbon 配置: server.port=9999 spring.application.name=ribbon-consumer #stores.ri ...

  3. windows7 安装pytorch

    这几天为了运行python的图像转换的项目,不得不安装pytorch,安装了两天,最后把经验记录一下. 如果版本不匹配会抛出很多错误,而网上的各种解决方式有大部分也解决不了问题. 在安装pytorch ...

  4. JavaScript创建对象的方式

    一.工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程. 考虑到在 ECMAScript 中无法创建类,开发人员就发明了一种函数,用函数来封装以特定接口创建对象的 ...

  5. jmeter使用手册

    1.在bin文件中找到jmeter.bat文件启动 2.创建测试计划-填写计划名称 3.添加线程组(右键点击) 4.设置线程-红框内均可设置,线程数-并发次数 5.在线程组下添加http请求 6.在h ...

  6. Codeforces1099D.Sum in the tree(贪心)

    题目链接:传送门 思路: 一个节点放的数越大,那么以它为根的子树的节点权值之和就越小. 所以我们要在合法的范围内,使偶数层节点的权值尽可能地大.也就是说,令它的权值是子节点的最小值,这样保证了它的子节 ...

  7. 更改手机系统的User-Agent & okhttp

    okhttp 和 volley 1. 之前用的是volley,其中一部分功能,比如User-Agent,是系统去处理的,改成okhttp库后,这部分功能需要浏览器自己处理 2. 具体区别可以参考: h ...

  8. 关于jstl中碰到的Property 'username' not found on type java.lang.String异常

    在jstl的forEach循环的时候总是有异常,刚开始以为是把类的属性名打错了,因为显示的是Property not found,但就算从类文件里面复制属性名过来依然显示的是Property not ...

  9. nginx日志分割

    mark 参考文章: https://blog.csdn.net/molaifeng/article/details/82667158

  10. 20164318 毛瀚逸 Exp1 PC平台逆向破解

    一.逆向及Bof基础实践说明 1.1实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 手工修 ...