pointers in Objective-C

Discussion in 'Mac Programming' started by OlyaGracheva, Dec 31, 2008.

  1. OlyaGracheva macrumors newbie

    Joined:
    Oct 17, 2008
    #1
    Happy New Year everyone!

    Hi there! I'm hoping that someone can help me out with the question below. I'm trying to understand pointers in Objective-C and am having a little difficulty in understanding the following. I'll be most grateful if someone can help. Many thanks in advance.

    Olya.


    From what I understand (and please correct me if I'm wrong):

    int x, count = 10;
    int *hello;
    hello = &count;
    x = *hello;

    Here the variables x and count are declared to be of type integer. Additionally, the variable count is assigned the value of 10.

    hello is a pointer to type integer. hello is then assigned the address of count.
    In order to access the value of count, hello must have an asterisk in front of it, ie, *hello.

    So, x is assigned the value of whatever is in count and in this case, 10.

    However...

    Fraction *myFraction = [[Fraction alloc] init];
    [myFraction someMethod];

    Here, if I understand correctly, myFraction is a pointer to an instance of Fraction class.

    myFraction is pointing to (or rather assigned the address of) an object which has been assigned memory and initialised.

    Surely, in order to access the object that myFraction points to, I ought to write:

    [*myFraction someMethod];

    Given the way in which x accessed the value of count, surely in order to access the object, one ought to write this and not:

    [myFraction someMethod];

    In addition, if I have

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSString *str = @"Programming can be a headache";
    NSLog (@"%@\n", str);

    Why is str being treated as an object above? Or is str an object and in which case, why would I want to make it point to an instance of NSString class? Surely, I ought to be able to just assign an object to str?

    Thank you again in advance.

    Happy New Year.
     
  2. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #2
    That's all correct. The asterisk is the dereference operator, which takes a pointer and returns the value at the address contained in the pointer.

    Right again.

    Nope, this is where Objective-C syntax kicks in, and you're not dealing with C any more. There are no "concrete" object instances in Objective-C. There are only pointers to objects. The message pass syntax in objective-C is an pointer to an object followed by the message to be passed, including parameters.

    @"" syntax is an NSString literal. This kind of expression evaluates to an NSString *. You can assign any NSString pointer to str, but in this case the @"" syntax is being used to generate an NSString rather than one of the NSString factory methods or initWith... initializers.


    Hope this helps. Good luck!

    -Lee
     
  3. OlyaGracheva thread starter macrumors newbie

    Joined:
    Oct 17, 2008
    #3
    Lee,

    Hi there! Thank you very much for your help. I very much appreciate your speedy response.

    You've been most helpful.

    Thank you.

    Olya
     
  4. Sander macrumors 6502

    Joined:
    Apr 24, 2008
    #4
    Like lee210 said, this is Objective-C syntax. You are quite astute for noticing this, though. In C++, a different object-oriented offspring of C, one would indeed have written

    myFraction->someMethod();

    using the "arrow operator" to indicate that myFraction is indeed a pointer. It is not that hard to get used to though, because in Objective-C all objects are referenced to through pointers.

    Have fun programming!
     
  5. OlyaGracheva thread starter macrumors newbie

    Joined:
    Oct 17, 2008
    #5
    Sander,

    Hi there! Thank you for that.

    Yes, little details like that annoy me but I'm glad there was a simple answer to the question. It never occurred to me that because Objective-C is OO, that its syntax would differ from C (a language that isn't OO). I guess I just presumed that because Objective-C is an extension of C that its syntax would be similar.

    Still, I'm glad I asked.

    Happy New Year.

    Olya.
     
  6. oshybrid macrumors newbie

    Joined:
    Jan 9, 2009
    #6
    But where is the object???

    Fraction *myFraction = [[Fraction alloc] init];
    [myFraction someMethod];


    Here, if I understand correctly, myFraction is a pointer to an instance of Fraction class.

    As I get that part too.

    myFraction is pointing to (or rather assigned the address of) an object which has been assigned memory and initialised.

    I get this first part about a pointer being assigend to an object . . . but the question for me is . . . What object? Where is it? I don't see the object getting instantiated. How does the pointer get assigned to said object?



    Or is the way it goes . . .


    Fraction *myFraction = [[Fraction alloc] init];


    Where a Fraction object is allocated memory and initializes, but is not given an actual variable name like most other languages. Its just a Fraction object out in space with a tether to the pointer of myFraction?
     
  7. Catfish_Man macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #7
    -alloc gets some memory on the heap, init initializes it, = assigns its address to a variable, and Fraction *myFraction declares a pointer named myFraction to be assigned to.

    This is similar to Fraction *myFraction = malloc(sizeof(Fraction)); in C.
     
  8. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #8
    Catfish_Man pretty much covered it, but when you ask "where" a Fraction object is, and stated that it's "not given a variable name". The "where" is on the heap, the area of memory used for dynamically allocated space. Essentially if something is not on the stack (which is used for storing local variables for a particular stack frame, which is generally one per function call), it is on the heap. A few things might be in the program's data area (literals that appear in your code, etc.), but otherwise it's heap or stack.

    The statement about not being given a variable name confused me a bit. There are some OO languages that allow local objects that can live on the stack. C++ is an example. You can have a pointer to an object, and use new to allocate space for it on the heap and store the address, also. This is simply not supported by Objective-C. Every object lives on the heap. You could technically alloc an object without storing it's pointer, so there's no "name" associated with that memory. This will likely cause a leak, however. In most cases the "name" for this new object is the variable in which the memory address for the newly allocated object is stored. This is the same when you, for example, malloc memory in C. There is no name for the space allocated, it's just a void * that you can cast to the pointer type you desire, and assign it to a pointer variable.

    There are all sorts of different ways languages handle these things. In Java every object lives on the heap, and everything is a pointer. You don't see *s all over, because when you say String, the item on the stack is a pointer to a String, and you assign a pointer to it with a string literal, or you can use new to allocate and initialize a new Object on the heap.

    The reason you say that the object is never instantiated (which means generating a concrete copy of an abstract "thing", in this case a class) is likely because the syntax is new to you. Whether an Object in Objective-C is instantiated at the time of allocation or initialization is probably up for debate, but since there are many interfaces that return different types of Objects at initialization time, it's probably easiest to consider initialization the point that the true Object is instantiated.

    Hopefully this clarifies things a bit for you. If not, don't hesitate to ask.

    -Lee
     
  9. chessdr macrumors newbie

    Joined:
    Jan 28, 2010
    Location:
    Utah
    #9
    So why are the parens needed in the getters around NSString* below?

    --------------------------------------------------------------

    #import <Cocoa/Cocoa.h>

    @interface Photo : NSObject {
    NSString* caption;
    NSString* photographer;
    }
    - (NSString*) caption;
    - (NSString*) photographer;

    - (void) setCaption: (NSString*)input;
    - (void) setPhotographer: (NSString*)input;

    @end
     
  10. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #10
    Because that's the Objective-C syntax. If a return value is a primitive, it would still be in parens. If the type of a parameter was a primitive, still in parens. That's the required syntax.

    -Lee
     
  11. Sydde macrumors 68020

    Sydde

    Joined:
    Aug 17, 2009
    #11
    Code:
    - ([COLOR="RoyalBlue"]NSString*[/COLOR]) photographer;
    In this case, you are specifying the type of the return value.

    Code:
    - (void) setPhotographer: ([COLOR="RoyalBlue"]NSString*[/COLOR])input;
    In this case, you are specifying the type of parameter that the method expects.

    The parens themselves are standard C syntax used in type casting.

    Note also the "-" used at the beginning of the method declaration. This is to indicate an "instance method" which will be called in the context of an instantiated object (the object's instance variables will be visible within the method). You will also see methods declared with a "+" instead: these are class methods, in which no instance variables are visible to the method.
     
  12. tjsimmons macrumors newbie

    Joined:
    Feb 11, 2010
    #12
    This is also something I've been struggling with; I have a passing knowledge of C, and I'm currently taking C++ this semester (online), but I'm learning Objective-C for work for some iPhone/iPad development.

    So basically, almost everything (definitely all objects) is created as a pointer, and that's that. There's no rhyme or reason, at least none I need to fully understand (although that would be nice), but that's just how it is?

    This thread's definitely been very helpful, I guess I just don't quite grasp the concept of a pointer.. I know that it POINTS to an address in memory (hence the *) and that value stored in memory can be retrieved using &, but that's about all I get.

    Thanks!
    T.J.
     
  13. GorillaPaws macrumors 6502a

    GorillaPaws

    Joined:
    Oct 26, 2003
    Location:
    Richmond, VA
    #13
    The reason pointers are so useful is because they're very lightweight and so it allows your program to operate much faster.

    To use a metaphor: let's say you were trying to map out the arrangement of cargo containers on a container ship. You could physically move each container around with a crane, but it would be much easier to use a diagram and do your calculations on the representation of the actual containers before using the crane.

    Pointers are using the same principle. They are just addresses to the location of the object they represent.
     
  14. tjsimmons macrumors newbie

    Joined:
    Feb 11, 2010
    #14
    Good metaphor. Makes a bit more sense. I didn't really think about the cost of digging into memory, changing an object, and putting it back.. this whole memory management thing is new to me with Objective-C. My programming background is mainly web-based.. and I don't deal with memory in HTML or JavaScript, haha.

    Thanks.
     
  15. Catfish_Man macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #15
    Javascript also uses pointers to refer to objects, it's just not as explicit about them.
     
  16. dougBrooks macrumors newbie

    Joined:
    Sep 21, 2010
    #16
    Hey everyone,

    Great thread! I'm still confused by one thing here that I'm just not wrapping my head around.

    There are examples in setter or methods that look like (NSString *):

    Code:
    - (void) setPhotographer: (NSString*)input;
    yet inside a method I've seen this syntax

    Code:
    NSString *str = @"Test";
    What does the * mean in the (NSString version)? Is this a pointer to the result of the setter/method or just saying it's expecting a point of type NSString.

    Thanks much!
     
  17. MorphingDragon macrumors 603

    MorphingDragon

    Joined:
    Mar 27, 2009
    Location:
    The World Inbetween
    #17
    Its saying the method parameter expects a pointer type of NSString. (Or id or nil, but the compiler will give a warning) The mothod itself returns void (or nothing)



    This one:
    Code:
    NSString *str = @"Test";
    That creates a pointer that points to the string literal @"Test" somewhere in the program itself.
     
  18. foidulus macrumors 6502a

    Joined:
    Jan 15, 2007
    #18
    I actually recommend learning C before you really jump into objective-c. Not only is Objective-C a superset of C(so you will be learning some objective-c along the way), by learning C you will really get a much better idea of what the compiler and your computer are actually doing.

    Understanding things like pointers and the cost of memory access etc. are pretty fundamental to writing well-behaved code. I actually recommend people learn C before they learn ANY high level language as it gives you a much better grasp of not only what is going on, but why certain things are the way they are.
     
  19. iEdd macrumors 68000

    iEdd

    Joined:
    Aug 8, 2005
    Location:
    Australia
    #19
    Sorry for bumping an old thread, but I only have a quick question and this thread is still on the first page anyway. :eek:

    I look at the code, and think that I want to do Object.someMethod(), which in Objective-C is [Object someMethod]. Whenever I see a pointer, I think of it as a memory address, eg 0x01fe9782, which is just an integer.

    eg. char *ptr = 'a' // ptr has a value of 0x07dc8314

    From now on, using ptr would give you the memory address, and using *ptr would give you the object at that memory address, in this case, 'a'.

    So when I see:
    Object *myObject = [[Object alloc]init];
    then:
    [myObject someMethod];
    I see it like this:
    [0x01fe9782 someMethod];
    Which just doesn't make sense. How can the number of a memory address have a method?

    I know this is wrong, but the following would make more sense to me:
    [myObject* someMethod];
    (Dereferencing to find the object at that memory address and then performing the method on the object.)

    Can anyone explain why this is? I can't get around the fact that it reads as if you are operating on the pointer and not on the object.
     
  20. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #20
    You're too wrapped up in the low-level mechanics. The number of a memory address doesn't have a type, either, yet dereferencing a pointer to a char has a completely different result than dereferencing a pointer to a double. For example:
    Code:
    int n = *aptr;
    
    produces very different code (and results) depending on whether aptr is declared as pointer to char or pointer to double. Worse, you can reinterpret one type as another, even if aptr is declared as pointer to void:
    Code:
    int n1 = *((char*)aptr);
    int n2 = *((double*)aptr);
    
    How is all that possible with the same "number of a memory address"? The answer lies in the interpretation of the memory address at a higher level of abstraction than simply a memory address number. Abstraction is at the heart of all computer programming.

    You are operating on the pointer. It comes down to what operation you're performing on the pointer.

    Sending a message to an object is compiled into a call to the C function objc_msgSend(). That function takes a pointer to an object, not an object parameter. That is, it takes a reference to an object struct, not a private copy of an object struct.

    The reasons for this should be obvious if you break it down. In order to operate on a thing pointed at, you either need a pointer to the thing (call by reference), or you need a private copy of the thing (call by value). Alterations to private copies have no effect on the original thing pointed at, so if one potential goal is to alter the original thing pointed at, there's only one option left: call by reference.

    It's also the same reason that C arrays are passed by reference, not by copy. Even in languages like Java, all arrays and objects are passed by reference, not by copy. Only primitives are passed by copy (i.e. by value).

    http://developer.apple.com/library/...rence/ObjCRuntimeRef/Reference/reference.html

    http://developer.apple.com/library/...timeGuide/Articles/ocrtHowMessagingWorks.html
     
  21. iEdd macrumors 68000

    iEdd

    Joined:
    Aug 8, 2005
    Location:
    Australia
    #21
    Thanks chown33. I skimmed over your answer before and just got back to it to read properly. Noticed you had added even more! :)

    Yep, I already understood that much. For example, if you pull 10101000 from a location, it means very different things if interpreted as unsigned/signed ints or even a char.

    Ahh. I think I get it now. It just so happens that all methods of a class are defined to operate by pointer. You pass a reference, the method goes to that address and gets/sets things as needed.

    As you said, I was thinking of it in the same way as low-level mechanics, where you need to tell it you want to operate on the thing at the memory address, and not the address itself. Evidently, this happens by default with objects as everything is expecting the memory address to begin with!

    It does make sense. I spose hadn't really thought about it before. My other OOP experience is in Python, where almost everything is hidden from you, and Java, which conceals the fact you are using pointers in objects (eg. String str = new String, not String *str = new String).
     
  22. zippyfly macrumors regular

    Joined:
    Mar 22, 2008
    #22
    I have also had a lot of trouble with the above concepts. The friendly people in this forum really helped me understand it.

    So, may I offer these insights which took me a long time to get (because nobody has explained it to me like I am about to, to you) but this is how I understand it in my own way:

    When you use the brackets [ ] then you do not need to dereference with the * operator. Like others have said, the * is for C syntax. You can almost always assume that the first item after the opening [ is an object and you can just treat that [ to have a built-in dereferencing operation. The second item preceding the closing ] would be the message to send to that object.

    You continue to use * for C syntax, which most of the fundamental operations are, within Objective-C code. So *myVar is still a pointer holding address &myVar.

    Regarding (NSString*) myString:

    The way I look at it is, NSString* is the type. That means, it's a pointer to an NSString. So NSString* is different from NSString and different from int.

    So it's not actually NSString with a trailing *. It's NSString* entirely, as a data type (which in this case is a pointer to an NSString, or an NSString pointer).

    Perhaps the experts here can verify my understanding of the above.
     
  23. Catfish_Man macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #23
    That distinction is exactly why I prefer to write
    Code:
    NSString* foo;
    instead of
    Code:
    NSString *foo;
    Sadly, C breaks this a bit in one small place. To declare more than one NSString you would need
    Code:
    NSString *foo, *bar;
    I consider this to be a minor design bug in C that makes it harder to think about the correct type of things.

    Also, I like CFString's way of handling it, which is to use a typedef to make CFStringRef.
     
  24. zippyfly macrumors regular

    Joined:
    Mar 22, 2008
    #24
    It's always funny to me that NSString* foo is the same as NSString *foo.

    Does anyone know if this is due to the usual whitespace being ignored, or is it two separate validities for the syntax?

    It would confuse me less if it was the latter, actually. (Although I'm not confused now, but had been for a very long time).

    Anyway even though I am clear on this point now, I think I will start to just adopt Catfish Man's habit as the best practice, going forward, maybe even go as far as separate lines for the multiple pointer declarations.
     
  25. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #25
    It's insignificant whitespace being ignored.

    These all have the same meaning:
    Code:
    NSString* foo;  // post-star space
    
    NSString *foo;  // pre-star space
    
    NSString*foo;  // spaceless
    
    NSString
    *
    foo;  // newlined
    
    NSString /* commented */
    * // newlined
    foo  /* and accepted */
    ;  // this too
    
    The only time whitespace is significant is when it separates tokens that would otherwise be parsed as a single token. Since punctuation other than '_' is invalid in a C name, operators serve as delimiters between tokens. This can lead to some odd expressions:
    Code:
    foo = bar---quux;
    
    can be parsed as either of these:
    Code:
    foo = bar-- - quux;
    foo = bar - --quux;
    
    The correct one is the former.

    There is ample reason for the Obfuscated C Contest.
    http://en.wikipedia.org/wiki/International_Obfuscated_C_Code_Contest
     

Share This Page