C:双指针和Objective-C NSError双指针用法

时间:2014-01-08 16:52:49

标签: objective-c c pointers nserror double-pointer

我碰巧偶然发现了关于使用**的双星(NSError)用法的帖子。决定深入挖掘一下,这让我重新审视C

我已经在<{1}}上阅读了很多帖子(此处不重复),我理解他们为何会这样做。

所以,我决定在IDE(Xcode)中编写一个小片段,以便自己查看它。

NSError

方法:

int a = 10;
int b = 20;

int *c = &a;
int *d = &b;

int **e = &d;

NSLog(@"Before: a is: %d b is: %d", a, b);

[self testSingleStar:c]; 
[self testDoubleStar:e]; 

NSLog(@"After: a is: %d b is: %d", a, b);

输出:

之前:a是: 10 b是: 20

之后:a是: 33 b是: 22

- (void)testDoubleStar:(int**)x { int anotherValue1 = 22; **x = anotherValue1; } - (void)testSingleStar:(int*)x { int anotherValue2 = 33; *x = anotherValue2; } (通过单个指针)和a(通过双指针)的值都发生了变化。

所以,如果我们可以使用 仅使用单个指针 来更改(b)的值,为什么我们需要使用指向指针的指针到a以便我们可以在方法调用中修改NSError对象,其中NSError对象在其参数(NSError)中传递?

此外:

关于上述内容,将一些内容传递给&error中的参数实际上是将一个副本传递给参数(即使在单个指针的情况下,只有一个副本会被传递),所以任何改变在方法范围内制作的不会影响传递给它的原始值(这就是他们使用双星的原因)。

但上面的示例(其中只使用了一个指针)似乎与此相矛盾,因为单个指针(C)指向的值(即a确实发生了变化?

2 个答案:

答案 0 :(得分:4)

您可以通过向函数或方法提供foo来修改foo *类型的外部变量:

+ (void)doJobReturningInt(int *) { ... }

int a;
[MyClass doJobReturningInt:&a]; // may modify the value of the variable a;

到目前为止,非常好。

现在我们如何声明存储NSError对象的变量?使用NSError *类型:

NSError *error;

因此,如果我们想要修改它,我们需要提供一个指向其类型的指针,即NSError **

+ (void)doJobReturningError:(NSError **)outError { ... }

NSError *error;
[MyClass doJobReturningError:&error]; // may modify the value of the variable error;

请参阅?情况也是如此:要修改类型foo,请提供foo*

答案 1 :(得分:2)

这是因为你不能只有一个NSError对象......你只能通过指针处理Objective-C对象......所以理论上你可以拿一个指向NSError的指针并交换它的内容。它会破坏封装(其他东西可能依赖于曾经存在的那些数据。)。

也只是将指针重新分配给新值并不起作用,因为它不会影响调用者版本。

所以虽然看起来很诱人:

-(void)method:(NSError *)errObject
{
    //something like
    errObject = [NSError errorWithBlah:@"blah"]; // this will only change the local variable errObject, not the callers version, that pointer is just copied by value. 
}

 /// not real code, didn't check to see if my params are in the correct places etc.
-(void)mangler:(NSError *)errObject
{
    //something like
    errObject = realloc(errObject,sizeof *errorObject);
    memcpy(errObject,[NSError new],sizeof NSError);

    // you have killed the old version that may be in use.
}