- 前言
我们知道,在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字符串的指针,然后重新改变了它的指向,最后就修改完成了。
图示如下:
如有问题,希望指出,一起探讨交流!
网友评论