2016-01-24 82 views
0

在下面的代码中,b的地址在块内变化。为什么?如果它改变为b,为什么不为一个?变量的地址在块内变化

int b =42; 
    int *a = &b; 

    printf("%p", a); 
    printf("%p", &b); 



    void (^testBlock)(void) = ^(void) 
    { 
     printf("%p", a); //address not changed 
     printf("%p", &b); //address is changed 

    }; 
    testBlock(); 

    printf("%p", a); //address not changed 
    printf("%p", &b);//address not changed 
+0

相关(为了解更多关于发生了什么):[块如何捕获它的封闭范围之外的变量?](http://stackoverflow.com/a/17819142) –

回答

1

块与函数类似。试想一下:

void testFunc(int *a, int b) 
{ 
    printf("%p", a); 
    printf("%p", &b); 
} 

int b =42; 
int *a = &b; 

printf("%p", a); 
printf("%p", &b); 

testFunc(a, b); 

printf("%p", a); //address not changed 
printf("%p", &b);//address not changed 

给函数的调用已复制都ab局部变量(参数)的testFunc()碰巧也被命名为ab值。这些变量与其他范围中的ab不同。他们只有相同的价值。因此,参数的地址与其他变量的地址不同。

a的情况下,您打印的是其值,而不是其地址。所以,这是一样的,因为价值是被复制的。在b的情况下,您正在打印其地址。

+0

你就像..真棒? @Ken:D – Viki

+0

这是完全不同的。在你的例子中,函数范围内有'a'和'b'的新声明,这些变量与外部声明的同名变量无关(可以更改名称并且无关紧要)。在OP的代码中,只有一个'a'和'b'的声明,这在两个示例中都是可见的。 – newacct

+0

@newacct,块从捕获的当地人制造新的变量,他们只是不明显地宣布。实际上,新变量是'const',因此赋值给它们会产生错误。地址的变化实际上就是证明。在引擎盖下,它真的就像一个函数的调用。 –

-1

int bint *a有很大的不同,因为b是一个值,并a是参考。

块捕获它们需要执行的变量以避免在变量发布后访问变量。这对于值类型意味着它可能被复制(与将值传递给函数时相同的方式),这就是为什么您看到b的地址不同。

+0

你的答案应该是一些什么更多的描述。总是我得到它。谢谢! – Viki

+0

我不同意,我的回答完全覆盖了你的问题。 – EmilioPelaez

+1

'a'和'b'之间没有区别;他们都是变数;捕获时复制所有变量。块内部的'a'和'b'(分别为'&a'和'&b')的地址在外部不同。 “a”和“b”(分别为“a”和“b”)的值在块内部和外部是相同的,因为这是副本的要点。 – newacct

0

块保留从周围范围捕获的非__block局部变量的单独副本,因为块可能超过它们的创建范围。您可以将此单独副本视为块的一种“实例变量”该块在执行时透明地使用该对象。这个单独的副本被初始化为创建块时外部变量的值。

由于它是一个单独的副本,它将有一个不同于原始变量的地址(这就是为什么&b是不同的)。但是,该变量的两个副本的最初会相同(直到有人更改外部副本),因为该块的副本是使用外部副本的值进行初始化的(这就是为什么a在两个副本中都是相同的原因)。

+0

如果问题只是关于值类型('int','char','bool'),那么你的问题会是一个很好的答案,但是这个问题明确地问到为什么值和引用类型(指针)之间有不同的行为,尽管问题的一部分包含了这种不同行为的证据,但你的答案根本不包括在内。 – EmilioPelaez

+1

@EmilioPelaez:类型之间没有不同的行为。所有类型的语义都是一样的。 – newacct