加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

objective-c – 为什么这个块不是全局的?

发布时间:2020-12-16 07:05:23 所属栏目:百科 来源:网络整理
导读:请考虑以下代码: #include stdio.htypedef void (^block)();block foo() { char a = 'a'; return [^{ printf("%cn",a); } copy];}block bar() { const char a = 'a'; return [^{ printf("%cn",a); } copy];} 这就是为armv7编译的内容: _foo:@ BB#0: push
请考虑以下代码:

#include <stdio.h>

typedef void (^block)();

block foo() {
  char a = 'a';
  return [^{
    printf("%cn",a);
  } copy];
}

block bar() {
  const char a = 'a';
  return [^{
    printf("%cn",a);
  } copy];
}

这就是为armv7编译的内容:

_foo:
@ BB#0:
        push    {r7,lr}
        mov     r7,sp
        sub     sp,#24
        movw    r3,:lower16:(L__NSConcreteStackBlock$non_lazy_ptr-(LPC0_0+4))
        movt    r3,:upper16:(L__NSConcreteStackBlock$non_lazy_ptr-(LPC0_0+4))
        movw    r1,:lower16:(___foo_block_invoke_0-(LPC0_1+4))
LPC0_0:
        add     r3,pc
        movt    r1,:upper16:(___foo_block_invoke_0-(LPC0_1+4))
        movw    r0,:lower16:(L_OBJC_SELECTOR_REFERENCES_-(LPC0_2+4))
LPC0_1:
        add     r1,pc
        movt    r0,:upper16:(L_OBJC_SELECTOR_REFERENCES_-(LPC0_2+4))
        movw    r2,:lower16:(___block_descriptor_tmp-(LPC0_3+4))
        ldr     r3,[r3]
        movt    r2,:upper16:(___block_descriptor_tmp-(LPC0_3+4))
        str     r3,[sp]
        mov.w   r3,#1073741824
LPC0_2:
        add     r0,pc
        str     r3,[sp,#4]
        movs    r3,#0
LPC0_3:
        add     r2,#8]
        str     r1,#12]
        ldr     r1,[r0]
        mov     r0,sp
        str     r2,#16]
        movs    r2,#97
        strb.w  r2,#20]
        blx     _objc_msgSend
        add     sp,#24
        pop     {r7,pc}

_bar:
@ BB#0:
        movw    r1,:lower16:(L_OBJC_SELECTOR_REFERENCES_-(LPC2_0+4))
        movt    r1,:upper16:(L_OBJC_SELECTOR_REFERENCES_-(LPC2_0+4))
        movw    r0,:lower16:(___block_literal_global-(LPC2_1+4))
LPC2_0:
        add     r1,:upper16:(___block_literal_global-(LPC2_1+4))
LPC2_1:
        add     r0,pc
        ldr     r1,[r1]
        b.w     _objc_msgSend

令我困惑的是第一个块不是全局块.它是一个堆栈块然后被复制.这对我来说没有意义.这是我在C标准中忽略的原因,为什么编译器无法自动推断出a实际上可以被认为是const?

我正在构建这个Os,启用了ARC,这是我的铿锵版:

$clang -v
Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin12.4.0
Thread model: posix

解决方法

声明char a需要存储,这意味着foo中的块需要自己的变量a,该变量初始化为foo的a值.块的变量存储在它的“环境”中.

声明const char a不需要分配存储,除非采用a的地址(通过C语言规范).任何使用a的值都可以直接用其常量值替换.这意味着可以在没有任何环境的情况下编译bar.

所以这两个块的编译方式不同.

从理论上讲,编译器,如果语言规范不允许它,可能能够检查变量的声明和使用,确定它不是外部可见的,确定它的值在初始赋值后永远不会改变,并且它的地址永远不会被采用,然后用一个常数值替换变量……但这可能是一个很小的分析,如果有的话,可能是一个很小的回报.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读