亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

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

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難道不行嗎?希望大神賜教。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品国产欧美成人夜夜嗨| 久久精品人人爽| 精品无码久久久久久国产| 欧美激情伊人电影| 日韩中文在线中文网三级| 国产亚洲精品一区二555| 国产男女猛烈无遮挡91| 欧美日韩一区二区精品| 久久免费高清视频| 日韩av一区二区在线| 成人精品在线观看| 国产精品夫妻激情| 91中文字幕在线| 精品久久久久久久久国产字幕| 日韩电影中文字幕在线观看| 日韩一区二区精品视频| 国模精品视频一区二区三区| 欧美一区第一页| 国产精品高潮视频| 自拍偷拍亚洲在线| 色香阁99久久精品久久久| 91精品国产成人www| www日韩欧美| 一区三区二区视频| 欧美在线视频导航| 久久久免费电影| 精品久久久久久中文字幕一区奶水| 日本国产欧美一区二区三区| 九九视频直播综合网| 亚洲欧美变态国产另类| 2019中文字幕在线免费观看| 91精品国产91久久久久久| 久久人人爽人人爽人人片亚洲| 亚洲视频网站在线观看| 日韩欧美视频一区二区三区| 亚洲欧美国产精品专区久久| 国产精品18久久久久久首页狼| 欧美性猛交xxxxx免费看| 国产精品第七十二页| 国产色婷婷国产综合在线理论片a| 欧美大尺度电影在线观看| 久久视频免费在线播放| 欧美精品电影免费在线观看| 欧美日韩精品在线| 久久久久久久一区二区三区| 久久综合亚洲社区| 亚洲精品videossex少妇| 色综合五月天导航| 日韩成人中文电影| 国产视频久久网| 日本道色综合久久影院| 色在人av网站天堂精品| 欧美午夜宅男影院在线观看| 久99九色视频在线观看| 日韩av电影在线播放| 成人欧美一区二区三区黑人| 日本国产欧美一区二区三区| 欧美色道久久88综合亚洲精品| 国产亚洲a∨片在线观看| 综合国产在线观看| 国产91在线高潮白浆在线观看| www.日韩.com| 国产国语刺激对白av不卡| 久久综合久久八八| 久久久国产精品亚洲一区| 成人黄色网免费| 尤物九九久久国产精品的特点| 国产一区二区三区在线观看网站| 97视频在线观看网址| 国产精品揄拍500视频| 成人av在线网址| 日韩av大片免费看| www国产精品视频| 91在线免费观看网站| 精品福利樱桃av导航| 久久影视电视剧免费网站清宫辞电视| 色婷婷av一区二区三区久久| 色先锋资源久久综合5566| 久久精品99久久久香蕉| 97视频色精品| 色综合久久中文字幕综合网小说| 久久国产加勒比精品无码| 日韩成人av一区| 国产亚洲精品久久久久久777| 欧美限制级电影在线观看| 国产综合在线观看视频| 91免费精品视频| 国产精品嫩草影院一区二区| 国产精品免费一区二区三区都可以| 亚洲人线精品午夜| 91免费福利视频| 91沈先生作品| 国产精品第2页| 欧美福利视频在线| 久久久久久久国产精品| 欧美色播在线播放| 日韩电影在线观看永久视频免费网站| 欧美自拍视频在线观看| 国产欧美 在线欧美| 亚洲91av视频| 亚洲欧美综合精品久久成人| 国产精品久久久久久久久粉嫩av| 成人国产精品免费视频| 欧美小视频在线| 国模精品视频一区二区三区| 久久久久这里只有精品| 亚洲精品xxx| 中文字幕日韩视频| 欧美一级视频一区二区| 国产午夜精品一区理论片飘花| wwwwwwww亚洲| 岛国视频午夜一区免费在线观看| 亚洲色图第一页| 亚洲欧美一区二区三区久久| 亚洲天堂av在线免费观看| 欧美在线视频一区| 久久69精品久久久久久国产越南| 欧美成人国产va精品日本一级| 国产欧美最新羞羞视频在线观看| 欧美性猛交xxxx黑人猛交| 亚洲韩国欧洲国产日产av| 中文字幕亚洲欧美在线| 国产精品黄色av| 欧美韩国理论所午夜片917电影| 欧美激情精品久久久| 国产不卡在线观看| 成人欧美一区二区三区黑人孕妇| 亚洲精品日韩欧美| 久久九九国产精品怡红院| 911国产网站尤物在线观看| 久久国产精品电影| 亚洲a级在线观看| 欧美激情喷水视频| 中文字幕日韩欧美在线| 亚洲天堂日韩电影| 国产精品91一区| 国产精选久久久久久| 另类专区欧美制服同性| 色老头一区二区三区在线观看| 久久伊人精品一区二区三区| 国产福利精品av综合导导航| 欧美人成在线视频| 68精品久久久久久欧美| 国产精品一区二区电影| 欧美性xxxxx| 国产日韩欧美中文在线播放| 亚洲精品在线观看www| 欧美国产亚洲视频| 欧美劲爆第一页| 日韩网站免费观看| 欧美极品少妇与黑人| 久久最新资源网| 夜夜嗨av色综合久久久综合网| 日本国产欧美一区二区三区| 成人日韩在线电影| 日韩成人激情影院| 久久久97精品| 成人网址在线观看| 亚洲3p在线观看| 国产区精品在线观看| 成人激情免费在线| 2025国产精品视频| 日韩精品视频免费| 久久影院模特热|