为什么这个块不是全局的? [英] Why is this block not global?
问题描述
考虑以下代码:
#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
,该变量初始化为 foo
的a
的值.块的变量存储在其环境"中.
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屋!