2016-01-24 95 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