What is the Asterisk (*) in Objective-C For?

Discussion in 'Mac Programming' started by Kelmon, Feb 25, 2006.

  1. macrumors 6502a

    Kelmon

    Joined:
    Mar 28, 2005
    Location:
    United Kingdom
    #1
    OK, I'm looking to try and give something back to the Mac community by helping out on some of the open-source projects and wish to learn Cocoa with Objective-C. I've been working my way through the tutorials posted at cocoadevcentral.com but I've come across some syntax that I have no idea what its significance and no where have I seen it explained. For your information I'm coming to Cocoa and Objective-C from a Java background and my first experience of C has been the tutorials that I've worked through.

    Anyway, the issue that I have is that I keep seeing the asterisk symbol appearing in method and variable declarations, as illustrated in the following example:

    Code:
    #import <Cocoa/Cocoa.h>
    #import "Converter.h"
     
    @interface ConverterController : NSObject
    {
        IBOutlet NSTextField *amountField;
        IBOutlet Converter *converter;
        IBOutlet NSTextField *dollarField;
        IBOutlet NSTextField *rateField;
    }
    - (IBAction)convert:(id)sender;
    @end
    What the heck does that asterisk mean for the instance variables? Equally, the same sort of thing shows up in method invocations, such as the following:

    Code:
    NSArray * foo = SomeFunctionReturningAnNSArray();
    NSMutableArray * bar = [foo mutableCopy];
    [foo release];
    
    Much of everything else that I have read about the Objective-C language and the tutorials that I have performed make sense but this eludes me at the moment so can someone put me out of my misery? Thanks.
     
  2. macrumors 6502a

    Fender2112

    Joined:
    Aug 11, 2002
    Location:
    Charlotte, NC
    #2
    It defines the variable as a pointer. "Pointers are designed to hold memory addresses. With a pointer you can indirectly manipulate data stored in other variable."

    Most C / C++ books devote 1 or 2 whole chapters just on pointers. I'm still trying to understand them. :D
     
  3. macrumors 603

    notjustjay

    Joined:
    Sep 19, 2003
    Location:
    Canada, eh?
    #3
    It's a pointer.

    If you have a Java background then you already are familiar with object references (since practically EVERYTHING in Java is one). Java just doesn't let you mess with them as easily as C/C++ do. So:

    NSArray * foo = SomeFunctionReturningAnNSArray();

    Means the function is returning a reference to an object of type NSArray. foo is a variable which points to NSArray objects. foo is not an NSArray, it points to one.

    Like in Java, if you were to declare

    NSArray foo;

    You would not say that foo is an NSArray. Yet. It's just ready to point to one (and would currently point to NULL), until you do this:

    foo = new NSArray(...)

    NOW foo is pointing to an NSArray object.

    You can also have pointers to basic types:

    int i = 5; // i is a basic integer type
    int* x; // x is a POINTER to an integer
    x = &i; // x now points to the same memory space as i does

    Now we can "dereference" the pointer x and use it to change the value of i.

    *x = 7; // sets the variable where the pointer is pointing, to 7

    or

    (*x)++; // increment the variable x points to

    It would be the equivalent in Java of something like:

    Integer i = new Integer(5);
    Integer x;
    x = i;

    (Sort of, anyway.)

    Here's a good thorough tutorial on pointers: http://home.netcom.com/~tjensen/ptr/pointers.htm

    They are single-handedly the most powerful, yet potentially most annoying, feature of C/C++.
     
  4. jsw
    Moderator emeritus

    jsw

    Joined:
    Mar 16, 2004
    Location:
    Andover, MA
    #4
    Think of pointers as phone numbers. By themselves, just numbers (references to memory locations for pointers, digits for phone numbers). But... reference the pointer (call the number) and you get to the object (person) you want.

    However, you can't affect the object (person) by changing the value of the pointer (phone number) itself - altering the pointer value itself is like dialing a different phone number. No longer connects you to what it used to.
     
  5. thread starter macrumors 6502a

    Kelmon

    Joined:
    Mar 28, 2005
    Location:
    United Kingdom
    #5
    Hey guys, this is great information. At least I know what I need to look at and have a reasonable idea of what this gig is all about. Thanks very much!
     
  6. Guest

    caveman_uk

    Joined:
    Feb 17, 2003
    Location:
    Hitchin, Herts, UK
    #6
    In general, one reason pointers are used is because they are usually a lot smaller than the thing they point to. For example, a pointer is 4 bytes on an Apple system but could point to an array that has thousands of bytes. If you wanted to pass that array to a function what would be more efficient - passing the four bytes (saying this is where the array's at) or the whole array?

    Luckily with objective-C and cocoa you don't really have to worry about pointers that much apart from remembering nearly everything is one. In other C dialects pointers are a lot more involved.
     
  7. macrumors 6502a

    Fender2112

    Joined:
    Aug 11, 2002
    Location:
    Charlotte, NC
    #7
    I like this analogy. :)
     
  8. macrumors 601

    zimv20

    Joined:
    Jul 18, 2002
    Location:
    chicago
    #8
    nice one.

    when teaching pointers in the past, i've used this analogy:

    1. the object is the house
    2. the pointer to the house is its address
    3. the pointer to the address are instructions on where to find the piece of paper the address is written on
     
  9. macrumors 601

    zimv20

    Joined:
    Jul 18, 2002
    Location:
    chicago
    #9
    also, there's a very good reason for using pointers when passing objects / variables / arrays / etc to functions.

    in C and C++, unless specificed, things passed to functions are not passed by reference. rather, they are copied and the called function operates on its own copy which is destroyed when the function ends. i've seen this confuse many a programmer.

    consider:

    Code:
    void foo (int i)
    {
        i++;
    }
    
    int main (int argc, char** argv)
    {
        int i=0;
    
        foo(i);
    
        cout << i << endl;
    }
    
    the output will be zero.

    correct:
    Code:
    void foo (int* i)
    {
        (*i)++;
    }
    
    int main (int argc, char** argv)
    {
        int i=0;
    
        foo(&i);
    
        cout << i << endl;
    }
    
    there are actually a couple ways of doing it the "correct" way in C++, fwiw.
     
  10. macrumors 68000

    Soulstorm

    Joined:
    Feb 1, 2005
    #10
    Pointers are essential to intermediate-to-advanced levels of programming. While they can really be a pain in the ass (especially in C++) they can also save you a lot of time, and allow you to perform actions that couldn't perform otherwise.
     
  11. thread starter macrumors 6502a

    Kelmon

    Joined:
    Mar 28, 2005
    Location:
    United Kingdom
    #11
    OK, next stupid questions: what does the double asterisk (**) in the main method arguments signify, and why is an ampersand (&) used in the call to the foo method rather than an asterisk?

    Thanks for the clarification that C/C++ is not pass by reference since I've got very used to that in Java and it would undoubtedly have caught me out.
     
  12. macrumors 601

    zimv20

    Joined:
    Jul 18, 2002
    Location:
    chicago
    #12
    char** argv is a pointer to an array. an array of strings, actually, where a string is an array of characters.

    in C/C++, the main() always has those two arguments: argc is the number of token strings on the command line, and argv (where v is 'vector') contains all the values of the command line, including the name of the executable, any options, and the arguments.

    for example, for this execution command:

    % a.out file1 file2

    argc would be 3, and argv would be:
    argv[0] = "a.out"
    argv[1] = "file1"
    argv[2] = "file2"

    further:
    argv[0][0] = 'a'
    argv[2][4] = '2'

    in general, ** means a pointer to a pointer. basically, anytime you make a pointer to something (including another pointer), it means "where to find".

    & means "take the address of". it's how you make a pointer to something. the * means to dereference the pointer, if it's in code. if it's part of a declaration, it's simply indicating the variable is a pointer.

    consider this C++ fragment:
    Code:
    int i = 5;
    int *k = &i;
    int **j = &k;
    
    cout << i << endl;
    cout << k << endl;
    cout << j << endl;
    
    the output would look something like:
    Code:
    5
    0x09383fa4
    0x09383fac
    
    but changing it to:
    Code:
    cout << i << endl;
    cout << *k << endl;
    cout << **j << endl;
    
    would get you all 5's.
     
  13. macrumors 601

    zimv20

    Joined:
    Jul 18, 2002
    Location:
    chicago
    #13
    it may help if i answer this more directly by commenting my code...

    Code:
    //
    // foo (int* i) declares a function called foo, returning a void, that takes
    // as a single argument a pointer to an integer. any changes made to the
    // value of the integer at that address will survive once foo finishes
    // executing (what we call "popping off the stack").
    //
    // note that because the * is part of a function definition, it's not actually
    // dereferencing i at this point.
    //
    void foo (int* i)
    {
        // this statement increments, by one, the value found at the memory
        // location passed in. this statement is equivalent to: *i = *i + 1;
        //
        // note that because this is not a statement of declaration, but rather
        // a statement to be executed, * here means to dereference the pointer,
        // which in this case gives us an integer.
    
        (*i)++;
    }
    
    int main (int argc, char** argv)
    {
        // declare an integer in this scope.
        int i=0;
    
        // because we wish to change the value of i in foo(), and have that
        // change reflected in this scope, we must pass the value in by
        // using a pointer. using the & is one way of doing that, it means to take
        // the memory address of i and pass that to foo. we use this method
        // because foo() expects a pointer to an integer.
        foo(&i);
    
        cout << i << endl;
    }
    
    if you're not confused enough, i'll tell you the other way the C++ handles passing by reference (called "passing by reference"), which is much more like java. i'll highlight the changes:
    Code:
    void foo ([color=red]int&[/color] i)
    {
        [color=red]i[/color]++;
    }
    
    int main (int argc, char** argv)
    {
        int i=0;
    
        foo([color=red]i[/color]);
    
        cout << i << endl;
    }
    
    this was adopted in C++ simply because it cleans up the code -- a lot of people get thrown by C-style pointers. of course, the & is used again, just to confuse people, but because the context is a function declaration, and not an executed statement, we know that we're not taking the address of something, we're defining the variable as pass by reference (as opposed to pass by pointer).

    because the signature of foo() changed, that meant we had to call foo() differently in main(). when passing by reference, it looks like pass by value (in fact, the only way to be certain is to look at the function definition of foo()).
     
  14. thread starter macrumors 6502a

    Kelmon

    Joined:
    Mar 28, 2005
    Location:
    United Kingdom
    #14
    Hey, zimv20, thanks for the explanations and examples. I think that I understand what is going on now but the implications of it are somewhat terrifying when compared to the relative simplicity of Java. I can quite easily see myself trying to work on pointers rather than the data that they point to simply because I forgot to add an asterisk or ampersand somewhere in my code. This looks like a nightmare waiting to happen...

    Still, at least I can read the example code that I am working through and understand what is going on now properly, which is certainly more than before where I was slightly confused.
     
  15. macrumors 68000

    Soulstorm

    Joined:
    Feb 1, 2005
    #15
    Already explained, just to add a clarification:

    in an array with one dimension (for instance, a simple string) you must know that the declaration name for this array is just a pointer to the first element of this array.

    Now, if you want to create a pointer to a 2 dimensional array of elements, you can declare it like this:
    Code:
    char **k;
    To a 3 dimensional array, the pointer is
    Code:
    char ***k
    and so on...

    That also means that you can handle the variable declared as an array as if it's a pointer. Look at this code:
    Code:
    int main(){
    	char k[] = "hello";
    	
    	cout << *(k+1);
    	
    	return 0;
    }
    This will show "e", because with the *(k+1) I told the program to show the element in the position k+1 (which k was a pointer in the first element, which means element 0) so it will show the second letter of your string.

    Note that pointers that come from array declarations cannot be directed to point into other arrays or in any other position apart from the array specified in general. However, you can create individual pointers that can point anywhere in your program.

    Do not be intimidated by the complexity of the pointers. They are here for a reason. Soon, as you begin to learn more and more about C++, you will see that it's a godsent gift for the intermediate and experienced programmer.
     
  16. macrumors 601

    zimv20

    Joined:
    Jul 18, 2002
    Location:
    chicago
    #16
    kelmon -- i edited post #12 because i made an error in how i described argc and argv. it's now correct.
     
  17. macrumors newbie

    jfgrissom

    Joined:
    May 14, 2009
    Location:
    San Diego, CA
    #17
    WOW... Great Explanation!

    Hi,

    I don't post often... but I just wanted to thank everyone here for putting this discussion together...

    In 15 minutes of reading you guys have given me what I haven't been able to find in 3 months of learning Objective-C from many books.
    (All the books say, read up on references at X. So I go to X and find lots of theoretical discussions... but nothing practical like this...)
    :D

    It does leave me with two questions unanswered though...

    NSArray *myArray /*Based on the conversation here... this points to an NSArray at the location *myArray. That makes PERFECT sense now... thanks!*/

    VS.
    NSArray * myArray /* What is this a reference too...? :confused:*/

    VS.
    NSArray* myArray /* Is this a Pointer to a Class? And if so, how would someone us it, if it is used at all? :confused:*/

    Hope this post isn't so old that it is long forgotten... hehe
    :D
     
  18. macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #18
    C is whitespace-insensitive. Those are all the same thing.
     
  19. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #19
    Like using Objective C objects. :rolleyes:
     
  20. macrumors member

    teek

    Joined:
    Feb 12, 2008
    Location:
    Norway
  21. macrumors 68000

    Joined:
    Sep 10, 2008
    Location:
    Asheville, NC
    #21
    I know I'm responding to an ancient post here, but I feel the need to say:

    Objective-C, like C and C++, does NOT pass by reference. Objective-C objects themselves are always passed around as C-style pointers, but they must be declared as such, and those pointers are copied--not passed by reference. Any object is passed exactly as it would have been in C. That is, an int would be copied unless passed as a pointer to an int; a pointer to an object will be copied unless passed as a double-pointer to an object.
     
  22. Riv
    macrumors newbie

    Joined:
    Jun 5, 2010
    #22
    I know this thread is old, but I noticed one other thing with the asterisk that confuses me. I apologize, I am very new to programming in general and decided to start with Objective-C. :)

    what is the difference between:

    (NSArray) *myArray

    and

    (NSArray *) myArray
     
  23. macrumors 603

    Cromulent

    Joined:
    Oct 2, 2006
    Location:
    The Land of Hope and Glory
    #23
    Technically they are casts. The first casts the value pointed to by myArray as a NSArray, the second casts the value in myArray as a pointer to NSArray.
     
  24. macrumors newbie

    jfgrissom

    Joined:
    May 14, 2009
    Location:
    San Diego, CA
    #24
    Ah...

    Now it makes even more sense!

    I guess I was just confusing myself for no reason... LOL

    Thanks for the clarification!
     

Share This Page