在块内时变量的地址正在更改

Address of a variable is changing when inside a block

在下面的代码中,b 的地址在块内时发生变化。为什么?如果 b 发生变化,为什么 a 不发生变化?

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

int bint *a是完全不同的,因为b是一个值而a是一个引用。

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

的不同地址的原因

一个块类似于一个函数。考虑:

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,您正在打印它的地址。

块维护从周围范围捕获的非__block局部变量的单独副本,因为块可能比创建它们的范围长。您可以将这个单独的副本视为一种"instance variable" 块在执行时透明使用的块对象。这个单独的副本在创建块时被初始化为外部变量的值。

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