2016-08-02 4 views
1

까다로운 목표 - C 블록 동작 : 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 나는 다음과 같은 동작에 대한 설명을 얻을 기쁠 것

에 의해 j을 수정 이유 :

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; 
} 

위의 코드는 다음과 같은 출력을 보여줍니다 블록 다음에 오는 과제?

그것은 우리가 __block 수정을 제거하는 경우, 우리는이를 얻을 것이다 언급하는 것이 재미있다 : 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

나는 위의 행동에 어떤 설명을 주셔서 감사합니다!

답변

3

저장 유형 __block 저장 유형을 사용하면 블록 외부 변수의 변경 사항을 블록 내부에서 볼 수 있으며 그 반대의 경우도 마찬가지입니다. j = k 라인은 두 번째 for 루프에서 블록 자체가 실행되기 전에 실행되어 블록에 할당 된 후 j이 표시됩니다.

__block을 제거하면 할당 전에 블록을 만들 때 블록이 j 값을 그대로 캡처합니다. 이상한 결과를 초래하는 초기화되기 전에 j을 캡처하기 때문에 __block을 제거한 후에 정의되지 않은 동작이 호출됩니다.

선언을 int j = 0으로 변경하면 로그 문은 모두 예상대로 j=0으로 표시됩니다.

+0

응답 해 주셔서 감사합니다. 그러나'j'는 다음주기에 계속 올라갑니다. 그래서'j' 변수의 범위를 벗어나기 전에'j'에 할당 된 마지막 값으로 103이 모두되지 않는 이유는 무엇입니까? – ishahak

+0

루프 안에'j'를 재 선언하면 각 블록은 자신이 참조하고있는'j'를 갖게됩니다. 루프 밖에서'__block int j; '를 움직이면 모든 블록은'j = 103'을 출력 할 것입니다. – dan

+0

Thanks @dan. 나는 당신의 대답을 받아 들일 것입니다. 즉,'__block' 변수는 실제로 블록 내의 정적 변수이지만, 선언 범위가 존재하는 한 블록 외부에서 액세스 할 수 있습니다! – ishahak

0

with __block j 변수가 블록으로 포인터로 전달되므로 할당 후 블록을 호출하면 j=k j가 100이됩니다.

__block없이 j 변수의 값만 블록으로 전달됩니다. 블록 자체는 값이 전달 된 블록 정의 이후에 j를 변경할 수 없습니다. 그래서 j는 0입니다.