Reputation: 6795
I'd be glad to get explanation for the following behavior:
typedef void (^MyBlock)(void);
MyBlock g_ary[4];
int runBlockParam2(MyBlock callbackBlock, int num) {
g_ary[num] = callbackBlock;
return num+100;
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
int i;
for (i=0; i<4; i++) {
__block int j;
int k = runBlockParam2(^{
NSLog(@"in the block i=%i, j=%i", i, j);
}, i);
j=k;
}
for (i=0; i<4; i++) {
g_ary[i]();
}
}
return 0;
}
The above code shows the following output:
in the block i=0, j=100
in the block i=1, j=101
in the block i=2, j=102
in the block i=3, j=103
Why is j
modified by the assignment which follows the block?
It is interesting to mention that if we remove the __block
modifier, we will get this:
in the block i=0, j=0
in the block i=1, j=100
in the block i=2, j=101
in the block i=3, j=102
I'll appreciate any explanation to the above behavior!
Upvotes: 1
Views: 97
Reputation: 4218
with __block the j variable will be passed into block as a pointer so if you call the block after the assignment j=k
j is 100 now.
without __block only the j variable's value is passed into block. block itself couldn't change j after the block definition in which the value is passed. so j is 0
Upvotes: 0
Reputation: 9825
The __block
storage type causes any changes to the variable outside of the block to be seen inside of the block and vice-versa. Your j = k
line runs before the block itself is run in your second for loop so the block sees j
after it has been assigned.
Removing the __block
causes the block to capture the value of j
as it is when the block is created which is before the assignment. You're invoking undefined behavior after removing the __block
because you are capturing j
before it has been initialized which leads to the strange output.
If you change your declaration to int j = 0
then the log statements would all show j=0
as you would expect.
Upvotes: 3