- 前言
我們知道,在C語言中,基本數據類型做為形參傳遞是無法直接更改其值的,因為是值傳遞,在函數中更改完畢后系統會收回為此函數分配的內存能及里面的局部變量。如果想要更改,可以通過指針,根據地址找到找到對應的值,然后可以更改。
- 問題
那么問題來了,比如在OC中,拿NSString為特例,我聲明的NSString明明也是NSString* ,并且我傳遞的也是NSString*指針,但是為什么不能更改?代碼如下:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSString *str = @"made";
NSLog(@"1----%p",str);
NSLog(@"2----%p",&str);
[self stringTestChange:str];
NSLog(@"after - %@",str);
}
- (void)stringTestChange:(NSString *)aString{
NSLog(@"3----%p",aString);
NSLog(@"4----%p",&aString);
aString = @"madeChina";
}
上述打印結果:
打印結果
可以看到值并沒有改變,但是從上述打印,我們也可以看到,str與aString的值是相同的,但是你會發現它們的地址去并不相同。
也就是說,在函數中aString是重新分配了內存空間,地址不一樣,但是它們指向的都是同一塊存儲空間,當再賦于新值給aString的時候,只不過是改變了它的指向而已,等函數結束后,原str的指向并未發生任何改變。當執行到打印after時,被改變的指向僅僅是aString,存儲結構大致如下:
圖解一
所以如果想通過函數改變原字符串,需要找到指向str的地址。所以更改如下:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSString *str = @"made";
[self stringTestChange:&str];
NSLog(@"after - %@",str);
}
- (void)stringTestChange:(NSString **)aString{
*aString = @"madeChina";
}
這樣再一打印,是沒問題的。
- 結論
為什么這樣可以?因為我們首先通過地址找到了str,然后通過*str找到了指向made字符串的指針,然后重新改變了它的指向,最后就修改完成了。
圖示如下:
圖解一
如有問題,希望指出,一起探討交流!