国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

block解析-block變量

2019-11-14 20:11:44
字體:
來源:轉載
供稿:網友

block變量

上一篇 講的是block靜態變量的特性,這里我們來看一下_block變量。引用官方:

You can specify that an imported variable be mutable—that is, read-write— by applying the __block storage type modifier. __blockstorage is similar to, but mutually exclusive of, the registerauto, and static storage types for local variables.

通過指定__block存儲類型修飾符,可以讀寫。__block存儲是類似的,但相互排斥的,寄存器,自動變量,和局部變量和靜態變量類型(后面這句不太理解)。 
我們來寫個例子,用__block修飾局部變量(對于全局變量是無效的,沒有任何作用,全局變量成員變量本身就可以在block內部修改,詳細看這一篇
void main1(){    __block char *_para1="a";    PRintf("init _para1:%s,%p,%p/n",_para1,_para1,&_para1);    void(^testBlock)(void)=^{        printf("exute _para1:%s,%p,%p/n",_para1,_para1,&_para1);    };    _para1="b";    printf("before _para1:%s,%p,%p/n",_para1,_para1,&_para1);    testBlock();    printf("after _para1:%s,%p,%p/n",_para1,_para1,&_para1);}
執行后輸出如下:
init _para1:a,0x47f4,0xbfffc9c0
before _para1:b,0x4829,0x8da4580
exute _para1:b,0x4829,0x8da4580
after _para1:b,0x4829,0x8da4580

這里加了__block修飾符。通過日志可以看出,block內部_para1的地址、值和執行前的_para1一樣,在block初始化后,對變量_para1的修改,可以同步到block內,block內并不是截獲了變量的值。我們可以看下通過clang 轉換后的后的cpp代碼:

//block 的實現函數的對象
struct __block_impl {  void *isa;  int Flags;  int Reserved;  void *FuncPtr;};
//block 引用的參數對象(每一個參數生成一個結構體)
struct __Block_byref__para1_0 {  void *__isa;__Block_byref__para1_0 *__forwarding; int __flags; int __size; char *_para1;};
//block對象
struct __main1_block_impl_0 {  struct __block_impl impl;  struct __main1_block_desc_0* Desc;  __Block_byref__para1_0 *_para1; // by ref  __main1_block_impl_0(void *fp, struct __main1_block_desc_0 *desc, __Block_byref__para1_0 *__para1, int flags=0) : _para1(__para1->__forwarding) {    impl.isa = &_NSConcreteStackBlock;    impl.Flags = flags;    impl.FuncPtr = fp;    Desc = desc;  }};
//block 的實現
static void __main1_block_func_0(struct __main1_block_impl_0 *__cself) {  __Block_byref__para1_0 *_para1 = __cself->_para1; // bound by ref        printf("exute _para1:%s,%p,%p/n",(_para1->__forwarding->_para1),(_para1->__forwarding->_para1),&(_para1->__forwarding->_para1));    }
//其他函數(copy、dispose:為了管理_Block_byref__para1_0 結構體變量的內存)
static void __main1_block_copy_0(struct __main1_block_impl_0*dst, struct __main1_block_impl_0*src) {_Block_object_assign((void*)&dst->_para1, (void*)src->_para1, 8/*BLOCK_FIELD_IS_BYREF*/);}static void __main1_block_dispose_0(struct __main1_block_impl_0*src) {_Block_object_dispose((void*)src->_para1, 8/*BLOCK_FIELD_IS_BYREF*/);}static struct __main1_block_desc_0 {  size_t reserved;  size_t Block_size;  void (*copy)(struct __main1_block_impl_0*, struct __main1_block_impl_0*);  void (*dispose)(struct __main1_block_impl_0*);} __main1_block_desc_0_DATA = { 0, sizeof(struct __main1_block_impl_0), __main1_block_copy_0, __main1_block_dispose_0};
//這是我們的測試函數
void main1(){    __attribute__((__blocks__(byref))) __Block_byref__para1_0 _para1 = {(void*)0,(__Block_byref__para1_0 *)&_para1, 0, sizeof(__Block_byref__para1_0), "a"};    printf("init _para1:%s,%p,%p/n",(_para1.__forwarding->_para1),(_para1.__forwarding->_para1),&(_para1.__forwarding->_para1));    void(*testBlock)(void)=(void (*)())&__main1_block_impl_0((void *)__main1_block_func_0, &__main1_block_desc_0_DATA, (__Block_byref__para1_0 *)&_para1, 570425344);    (_para1.__forwarding->_para1)="b";    printf("before _para1:%s,%p,%p/n",(_para1.__forwarding->_para1),(_para1.__forwarding->_para1),&(_para1.__forwarding->_para1));    ((void (*)(__block_impl *))((__block_impl *)testBlock)->FuncPtr)((__block_impl *)testBlock);    printf("after _para1:%s,%p,%p/n",(_para1.__forwarding->_para1),(_para1.__forwarding->_para1),&(_para1.__forwarding->_para1));}

發現和不加__block不太一樣,多了一個結構體(_Block_byref__para1_0)

struct __Block_byref__para1_0 {  void *__isa;__Block_byref__para1_0 *__forwarding; int __flags; int __size; char *_para1;};

這個結構體就是用__block 聲明的變量,聲明__block變量_para1 轉換后的代碼如下:

__attribute__((__blocks__(byref))) __Block_byref__para1_0 _para1 = {(void*)0,(__Block_byref__para1_0 *)&_para1, 0, sizeof(__Block_byref__para1_0), "a"};

其實就是生成一個_Block_byref__para1_0對象,__forwarding 指針指向變量結構體自己

void(*testBlock)(void)=(void (*)())&__main1_block_impl_0((void *)__main1_block_func_0, &__main1_block_desc_0_DATA, (__Block_byref__para1_0 *)&_para1, 570425344);

初始化block,傳遞結構體變量_para1、函數地址、描述信息等參數,block對象的成員 _para1 引用了_para1結構體的地址,這樣就可以修改_para1,而且外界對_para1結構體的修改都可以同步到block對象的成員_para1中,修改代碼如下:

(_para1.__forwarding->_para1)="b";

直接通過__Block_byref__para1_0 結構體的成員__forwarding(指向自己)取得_para1成員的地址,然后就可以讀寫,達到了修改變量的目的。

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

執行block,依然是通過調用函數指針 FuncPtr 實現,并傳遞block自身。函數體代碼如下:

static void __main1_block_func_0(struct __main1_block_impl_0 *__cself) {  __Block_byref__para1_0 *_para1 = __cself->_para1; // bound by ref        printf("exute _para1:%s,%p,%p/n",(_para1->__forwarding->_para1),(_para1->__forwarding->_para1),&(_para1->__forwarding->_para1));    }

在函數體內,通過block對象的成員_para1(__Block_byref__para1_0的指針,再通過自身的成員__forwarding指針來獲取_para1。

我的理解就是指針引用的關系,不知道為什么要加一個__forwarding指針 ,直接去引用自身的成員 _para1難道不行嗎?希望大神賜教。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 邵阳县| 玉龙| 鹰潭市| 黄浦区| 綦江县| 荥阳市| 宜兰市| 叙永县| 乌兰县| 稷山县| 阿城市| 鲁山县| 武夷山市| 昌都县| 哈密市| 平武县| 井冈山市| 聊城市| 哈密市| 象山县| 楚雄市| 沾化县| 十堰市| 清丰县| 增城市| 乐亭县| 宿迁市| 南安市| 临颍县| 双鸭山市| 来宾市| 九龙县| 洪湖市| 九台市| 永清县| 临安市| 元谋县| 台北县| 比如县| 元谋县| 华容县|