为什么这个块不是全局的? [英] Why is this block not global?

查看:73
本文介绍了为什么这个块不是全局的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码:

#include <stdio.h>

typedef void (^block)();

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

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

这是armv7的编译版本:

This is what that compiles to for 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, pc
        str     r3, [sp, #8]
        str     r1, [sp, #12]
        ldr     r1, [r0]
        mov     r0, sp
        str     r2, [sp, #16]
        movs    r2, #97
        strb.w  r2, [sp, #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, pc
        movt    r0, :upper16:(___block_literal_global-(LPC2_1+4))
LPC2_1:
        add     r0, pc
        ldr     r1, [r1]
        b.w     _objc_msgSend

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

What confuses me is the first block is not a global block. It's a stack block and then copied. That doesn't make sense to me. Is it something I'm overlooking in the C-standard for why the compiler can't automatically infer that a can actually be considered const?

我正在构建此Os,启用了ARC,这是我的clang版本:

I'm building this Os, ARC enabled, and here's my clang version:

$ 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,该变量初始化为 fooa的值.块的变量存储在其环境"中.

The declaration char a requires storage, and this means that the block in foo requires its own variable a which is initialised to the value of foo's a. The block's variable is stored in it's "environment".

除非使用a的地址(根据C语言规范),否则声明const char a不会要求要分配的存储. a值的任何使用都可以直接用其常量值代替.这意味着bar可以在没有任何环境的情况下进行编译.

The declaration const char a does not require storage to be allocated unless the address of a is taken (by the C Language Specification). Any use of a's value can be replaced directly by its constant value. This means that bar can be compiled without any environment.

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

So the two blocks are compiled differently.

理论上,如果语言规范不允许编译器,则它可以检查变量的声明和使用,确定其在外部不可见,确定其值在初始赋值后永不更改以及其地址永远不会被采用,然后用一个恒定值替换该变量...但是对于很多(如果有的话)回报来说,这是很多分析.

In theory a compiler, if the language specification doesn't disallow it, might be able examine the declaration and use of a variable, determine that it is not externally visible, determine its value never changes after initial assignment and that its address is never taken, and then replace the variable by a constant value... but that's a lot of analysis for probably a small, if any, payoff.

这篇关于为什么这个块不是全局的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆