0

In the following code, address of b is changing when it's within the block. Why? And if it changes for b, why not for 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
Viki
  • 421
  • 1
  • 4
  • 12
  • Related (for more understanding of what's going on): [How does a Block capture the variables outside of its enclosing scope?](http://stackoverflow.com/a/17819142) – jscs Jan 24 '16 at 19:05

3 Answers3

1

A block is similar to a function. Consider:

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

The call to the function has copied the values of both a and b to local variables (parameters) in testFunc() which happen to also be named a and b. Those variables are not the same as the a and b in the other scope. They just have the same value. Therefore, the addresses of the parameters are different than the addresses of the other variables.

In the case of a, you're printing its value, not its address. So, that's the same because the value is what has been copied. In the case of b, you're printing its address.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • You are like.. awesome? @Ken :D – Viki Jan 24 '16 at 18:39
  • This is very different. In your example, there are new declarations of `a` and `b` in the function scope, which are unrelated to the variables which happen to have the same name declared outside (you could change the names and it wouldn't matter). In the OP's code, there is just one declaration of `a` and `b`, which is visible in both scopes. – newacct Jan 26 '16 at 00:44
  • @newacct, blocks make new variables from captured locals, they just aren't visibly declared. In fact, the new variables are `const`, so assignments to them will generate errors. The change of address is, in fact, the proof of this. Under the hood, it really is just like a call to a function. – Ken Thomases Jan 26 '16 at 01:48
  • @KenThomases: I know that. I'm just saying that it's unrelated to your example, because you are passing arguments to parameters in a function. And parameters are always separate variables (as parameters are declared). But that doesn't say anything about the OP's case, since there's no passing involved. Capturing isn't passing. – newacct Jan 26 '16 at 02:05
  • @KenThomases: Consider JavaScript, where variables are always captured by reference and passed by value. If you somehow showed an example involving passing in JavaScript that demonstrates the parameter inside the function was an independent variable from the passed one in the caller, could you then say the same thing about capturing variables? But then you would be wrong, because captured variables in JavaScript are shared with the one in the calling scope. The point is, the way calling works says nothing about the way capturing works. – newacct Jan 28 '16 at 04:50
0

Blocks maintain a separate copy of non-__block local variables captured from the surrounding scope, since blocks may outlive the scope they were created in. You can think of this separate copy as a kind of "instance variable" of the block object that the block transparently uses when it's executed. This separate copy is initialized to the value of the outside variable at the time the block is created.

Since it's a separate copy, it will have a different address than the original variable (that's why &b is different). However, the value of both copies of that variable will be the same initially (until someone changes the outside copy), since the block's copy is initialized with the value of the outside copy (that's why a is the same in both).

newacct
  • 119,665
  • 29
  • 163
  • 224
  • Your question would be a good answer if the question was only about value types (`int`, `char`, `bool`), but the question explicitly asks why there is different behaviour between value and reference types (pointers), which your answer doesn't cover at all, even though part of the question contains proof of that different behaviour. – EmilioPelaez Jan 26 '16 at 16:04
  • 1
    @EmilioPelaez: There is no different behavior between the types. The semantics is the same for all types. – newacct Jan 26 '16 at 20:16
-1

int b and int *a are quite different because b is a value and a is a reference.

Blocks capture the variables they need to be executed to avoid accessing a variable after it was released. What this means for value types is probably that it gets copied (the same way it gets copied when you pass a value to a function), which is why you see a different address for b.

EmilioPelaez
  • 18,758
  • 6
  • 46
  • 50
  • Your answer should have been some what more describing..Anyway I got it. Thanks! – Viki Jan 24 '16 at 18:42
  • I disagree, my answer covered your question perfectly. – EmilioPelaez Jan 25 '16 at 03:51
  • 1
    There is no difference between `a` and `b`; they are both variables; all variables are copied when captured. The addresses of `a` and `b` (`&a` and `&b` respectively) will be different inside the block than outside. The values of `a` and `b` (`a` and `b` respectively) will be the same inside the block and outside, because that's the point of a copy. – newacct Jan 26 '16 at 06:17
  • @newacct They are both variables, obviously, but of course a pointer is different from a value. I suggest you try the code provided in the question, the only place the address is different is when you print `b` inside the block, because it was copied; `a` is not copied because it's a pointer, the same way objects are not copied when you pass use them within a block, they are just retained. What's more, if you change the value of `a` after declaring the block but before executing it, the value of `a` in the block will be the new value, because it wasn't copied, because it's a pointer. – EmilioPelaez Jan 26 '16 at 15:51
  • 1
    @EmilioPelaez: No, there is no difference. `a` and `b` are both copied (the integer `b` and the pointer `a` are both copied). The address of `b` is different, and the address of `a` is different. The original code did not print the address of `a` (`&a`). It printed the value of `a`, which since `a` is a pointer is the address contained within it. That `a` is a pointer is irrelevant to the semantics. You are confused because you are wrongly using "value of `a`" to refer to the thing that the pointer `a` *points to*. This is not the value of `a`. – newacct Jan 26 '16 at 20:19