原來簡書默認的編輯器是富文本
,必須從設置
里手動切換成MarkDown
才能使用···
真是坑···
下面是一個簡單的block使用場景:
int main()
{
void (^blk) (void) = ^{ printf("Block\n"); };
blk();
return 0;
}
使用clang -rewrite-objc
轉換成C/C++
代碼:
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
struct __main_block_impl_0 {
struct __block_impl impl; //注意此處不是結構體指針,而是拷貝結構體
struct __main_block_desc_0 *Desc;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags = 0) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself)
{
printf("Block\n");
}
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)
};
int main() {
//調用block構造函數初始化block的結構體并聲明賦值結構體指針
void (*blk) (void) = (void (*) (void)) &__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA);
//調用內部函數指針執行匿名函數的實現
((void (*) (struct __block_impl *))((struct __block_impl *)blk)->FuncPtr)((struct __block_impl *)blk);
return 0;
}
可以看出通過Block使用的匿名函數實際上被作為簡單的C語言函數來處理,匿名函數默認傳入了一個struct __main_block_impl_0
類型的結構體指針__cself
,此處匿名函數僅僅是調用了printf
打印一個寫好的字符串;但如果該block有截獲變量的瞬時值,這些瞬時值會被保存為block的struct __main_block_impl_0
類型的結構體中作為成員變量,匿名函數被調用時通過傳入的__cself
指針來訪問并使用這些成員變量的值。
如果上述main()
函數中增加變量聲明int val = 10;
,并且block中的打印函數改成printf(val);
,那么對應的struct __main_block_impl_0
結構體會變成:
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0 *Desc;
int val;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags = 0) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; }
};
而對應的函數實現會變成:
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
int val = __cself->val;
printf(val);
}
這就是為什么block捕獲的是自己被初始化時外部變量的瞬時值,而不受這些變量改變的影響。