views:

451

answers:

7

Hello! I'm coming from an Objective-C background and am trying to expand my knowledge in C. One thing has me confused, however, and that's the difference between pointers in C and Obj-C. As you can see in the examples below, things seem to behave a bit differently between both languages, and I was wondering if you could help explain why?

C code works fine:

void myFunction()
{
    int x, *pointerX; 
    pointerX = &x;
    *pointerX = 5;

    // Prints: "x is 5"
    printf("x is: %i", x);
}

Obj-C code fails:

- (void)myMethod
{
    NSString *string = @"Caramel coffee", *stringPointer;
    stringPointer = &string;                    // Warning:   Assignemnt from incompatible pointer type
    *stringPointer = @"Chocolate milkshake";    // Exception: Incompatible types in assignment

    NSLog(@"string is: %@", string);
}

Question: Why can't I assign stringPointer to the memory address of string (stringPointer = &string;), and why am I able to perform *pointerX = 5; under C, but I can't perform *stringPointer = @"Chocolate milkshake"; under Objective-C?

I realize that Obj-C deals with objects and C doesn't, but I can't seem to figure out the behind-the-scenes details as to why it doesn't work in Obj-C. Any help is greatly appreciated. Thanks! :)

+14  A: 

In your first example, x and pointerX have different types ((int) and (int *) respectively). In your second example, string and stringPointer have the same type (NSString *). Try instead:

NSString *string = @"Caramel coffee", **stringPointer;
caf
+3  A: 

&string has type NSString **, whereas stringPointer has type NSString *, thus the warning. Then you try to assign an instance of NSString (with type NSString *) to a variable of type NSString, thus the error.

swegi
+8  A: 

Your NSString *string is itself a pointer. Therefore, in order to point to it, you need to declare stringPointer as a pointer to a pointer. That is, declare stringPointer like this:

NSString **stringPointer;

Then everything should work. Note that the same pointer semantics apply in C and Objective-C.

Whisty
+2  A: 

It's always a good idea to define each variable on its own line. The when you rewrite your initial objective-с code like

NSString* string = @"Caramel coffee";
NSString* stringPointer;

many things become clear.

kemiisto
-1 Still doesn't fix the problem, since the pointer types are incompatible.
Quinn Taylor
@Quinn: at a moment when a wrote my message the problem was already solved. May be it's better to wright such style related messages in comments, but then there is no ability for code formatting.
kemiisto
+1  A: 
Matthias Wandel
A: 

What are you trying to do?

Not sure if it will work as you intended.

You seem to be taking concepts from C and apply it to Cocoa classes, I thought you were learning C. Have you seen anywhere in Objective-C code taking address of an object?

Cocoa classes are implemented using Class clusters which mean that they share the same interface but you will get specific extended class which you manipulate.

In your case you are taking address of possibly class that extends NSString and assign it to pointer to NSString.

Example:

NSString * str = @"Caramel coffee";
NSString * str2 = [NSString stringWithString:@"all"];

NSLog(@"%@", [[str class] className]);
NSLog(@"%@", [[str class] className]);

Output (GNUStep linux):

2009-12-08 10:49:29.149 x[25446] GSCInlineString
2009-12-08 10:49:29.149 x[25446] NSConstantString

... apart from the obvious pointer definition problems pointed out by others.

stefanB
The NSError pattern is probably the most common case where we take the address of an object in Objective-C: "NSError *error; [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"foo" error:
Jarret Hardie
Yes but we pass a address of local variable into a method because we expect value returned. But you would not generally see stuff like `NSString * str = `
stefanB
+2  A: 

The thing is that when you create an object, you actually always manipulate it through a pointer assigned to it, hence (NSString *).

Try doing the same thing in C (working with a string), perhaps it becomes clearer:

void myFunction()
{
    char *string = "this is a C string!";
    char **ptr=&string;


    // Prints: "this is a c string"
    printf("ptr points to %s: \n",  *ptr);
}

As you can see, pointers work in exactly the same way as they do in objective-c. Bare in mind that there are very few primitives in objective-c (int is the most obvious one). Most of the time you are creating a pointer of type object X (say NSString), and then allocating a chunk of memory (through [[Object alloc] init]) and assigining the start address of that chunk to your pointer. Exactly the same as we've done in C with our string.

lordsandwich