1. Post #1
    Gold Member
    s0ul0r's Avatar
    September 2006
    993 Posts
    Ok guys so now that I'm quite good at c#, I want to learn c++ and, as far as I can see it's quite easy for me to learn because I know c# already and they both are quite similar, BUT:
    Now I understand what pointers are, they are basically the memory address of a variable, right?
    But I just don't get what purpose they serve?
    Why not just access the variable itself directy? Why do it through a pointer?

    So I haven't read that much tutorials and books about c++ but that is a question that really is a worry to me...
    So uhm, could you guys tell me the purpose of pointers since I am used to c# and never really used pointers before.
    Oh and, I haven't coded a single c++ program, I'm just wondering...

    And please don't flame me if that question sounds noobish to all you l33t c++ coders ;)

  2. Post #2
    Gold Member

    March 2005
    3,028 Posts
    Why not just access the variable itself directy? Why do it through a pointer
    1. Duplicates eat valuable memory.
    struct FSCKING_HUGE {
        int OMGWTF[100000000];
    }
    void LOL(struct FSCKING_HUGE ASDF) {
        prinf("%d\n", ASDF.OMGWTF[0]);
    }
    
    LOL() will create a duplicate FSCKING_HUGE struct on the stack, which is a complete waste of precious resources.

    2. Sometimes you need to modify the original value from a function with a different scope.
    void swap(int* a, int* b) {
        int tmp;
        tmp = *a;
        *a  = *b;
        *b  = tmp;
    }
    
    It is impossible to implement this function without pointers. If you want to modify both "a" and "b", you must have their memory addresses.

    3. You can't build advanced data structures without pointers. This is the big one. If you ever get really serious about programming, you'll be implementing trees, heaps, graphs, etc. practically non-stop.

    There's also some funky tricks you can do with pointer casting and arrays, but that's mostly C-style antics.
    Reply With Quote Edit / Delete Reply Show Events Dumb Dumb x 4Bad Reading Bad Reading x 1Bad Spelling Bad Spelling x 1 (list)

  3. Post #3
    Wyzard's Avatar
    June 2008
    1,243 Posts
    Pointers are used when you create objects on the heap (i.e. with "new") rather than on the stack (i.e. local variables within a function). You put things on the heap when you need them to last longer than the scope they're created in, since local variables are destroyed when they go out of scope.

    For example:
    class MyClass { ... };
    
    MyClass *createOne() {
        MyClass foo;  // This instance is on the stack and will be destroyed when createOne() returns
        MyClass *bar = new MyClass();  // This instance is on the heap and exists until you delete it
    
        return bar;
    }
    
    int main() {
        MyClass *obj = createOne();  // This points to the actual object created above, not a copy
        // (Do stuff using obj here...)
        delete obj;  // Destroy the object now that we're done with it
    }
    

    The heap is also used when you want to create an array whose size isn't known until runtime. Since the size of an object (struct or class) is fixed at compile time, any variable-sized data held by an object has to be allocated separately. For example, if you create a std::string, it'll contain an internal pointer to a char[] that it allocates with new() and deletes in its destructor.

    In C, pointers are also used for passing function parameters by reference, and that can be done in C++ too, but C++ has a better way of doing that (using references).
    Reply With Quote Edit / Delete Reply United States Show Events Informative Informative x 2 (list)

  4. Post #4
    Gold Member
    jA_cOp's Avatar
    May 2006
    2,691 Posts
    When you pass variables to a function in C or C++ (unless you explicitly use C++ references), it copies that value. This is true for structs and classes as well.

    Say we wanted to change a variable from another function:
    #include <iostream>
    
    void foo(int var)
    {
        var = 1;
    }
    
    int main()
    {
        int a = 0;
        foo(a);
        std::cout << a << std::endl;
        return 0;
    }
    
    This will print "0" because when you pass "a" to the "foo" function, the value is copied, so the original variable "a" is left unchanged.

    This is the same as in C#, except for classes, they are passed by reference implicitly in C#. To achieve the wanted behaviour in C#, you'd use the "ref" or "out" keywords.

    In C++, you can use a pointer to achieve this:
    #include <iostream>
    
    void foo(int *var) //Receive a pointer to an int
    {
        *var = 1; //Dereference pointer and set value to 1
    }
    
    int main()
    {
        int a = 0;
        foo(&a); //pass address of a to foo
        std::cout << a << std::endl;
        return 0;
    }
    

    But the preferred C++ way is to use references (In C, you don't have these):
    #include <iostream>
    
    void foo(int& var) //Receive a reference to an int
    {
        var = 1; //Set value referenced by var to 1
    }
    
    int main()
    {
        int a = 0;
        foo(a); //pass a
        std::cout << a << std::endl;
        return 0;
    }
    

    References are better because they allow for a nicer, seamless syntax and they are a lot safer than pointers. References have a lot of restrictions on them (which is a good thing), so sometimes your only bet is to use a pointer. The general rule is; use pointers whenever you can't do it with references.

    There is a lot more to pointers than this, but this is the typical case. For classes and structs you also want to use pointers or references to make them work like you'd expect in C# (see above posts for more on this).

    The heap is also used when you want to create an array whose size isn't known until runtime.
    In C99, you can create variable size arrays on the stack.
    Reply With Quote Edit / Delete Reply Norway Show Events Informative Informative x 3 (list)

  5. Post #5
    Wyzard's Avatar
    June 2008
    1,243 Posts
    In C99, you can create variable size arrays on the stack.
    I thought about mentioning that, but wanted to keep my response relatively simple since it's a beginner question. You're right, though, so to fill in the details: variable-length arrays are part of C99, but not C++98; compilers may support them but it's a non-standard extension until C++0x is finalized. They can only be used for arrays that are local variables within a function, not member variables in a struct or class, and they can't be reallocated (e.g. to change their size).
    Reply With Quote Edit / Delete Reply United States Show Events Agree Agree x 1 (list)

  6. Post #6
    Gold Member
    Cathbadh's Avatar
    March 2006
    1,071 Posts
    instantiating things of variable size on the stack is discouraged. It doesn't inherently check for stack overflows, and it is a good way to trigger exceptions in your code.

  7. Post #7
    Gold Member
    s0ul0r's Avatar
    September 2006
    993 Posts
    Thanks guys, that helped me to understand pointers way better, and jA_cOp, your example really gave me an idea what they are used for, f.e. to modify variables directly in the memory when that would be impossible without pointers.
    Reply With Quote Edit / Delete Reply Germany Show Events Friendly Friendly x 2 (list)

  8. Post #8
    Gold Member
    Cathbadh's Avatar
    March 2006
    1,071 Posts
    Without pointers you can't have linked lists or trees or graphs or really any cool and useful data structure.

  9. Post #9
    Gold Member
    PvtCupcakes's Avatar
    May 2008
    10,900 Posts
    Kind of a bump, but I have a quick question.

    In C, if you want to pass a string to a function and have the string be modified and returned without the return statement would you use a double pointer?

    I know char* is the same as char[], so you would pass a char** right?

    So something like this:
    void modify(char** c, char** d)
    {
      *c = strcat(c, "a");
      *d = strcat(d, "b");
    }
    
    Reply With Quote Edit / Delete Reply United States Show Events Funny Funny x 3Agree Agree x 1 (list)

  10. Post #10
    Gold Member
    gparent's Avatar
    January 2005
    3,949 Posts
    I know char* is the same as char[]
    It's not.

    Maybe I'm stupid - Why can't you do this?

    void modify(char* c)  
    {  
    	c = strcat(c, "a");  
    }
    

    Am I not understanding your question properly? I hardly even use C strings.
    Reply With Quote Edit / Delete Reply Show Events Dumb Dumb x 1Bad Spelling Bad Spelling x 1Bad Reading Bad Reading x 1 (list)

  11. Post #11
    Gold Member
    PvtCupcakes's Avatar
    May 2008
    10,900 Posts
    It's not.

    Maybe I'm stupid - Why can't you do this?

    void modify(char* c)  
    {  
    	c = strcat(c, "a");  
    }
    

    Am I not understanding your question properly? I hardly even use C strings.
    Since char* can be used for strings, it's basically the same as char[].
    So if I wanted to modify the memory allocated to the array, I think I'd have to use a pointer to the array, thus char**. I'm not sure though.
    Reply With Quote Edit / Delete Reply United States Show Events Agree Agree x 1 (list)

  12. Post #12
    Gold Member
    VoiDeD's Avatar
    August 2005
    860 Posts
    char* can be a pointer to an array.

    A pointer can be a pointer to anything, a int* could point to a 256 byte block of memory containing anything. The type of the pointer is only meaningful when dereferencing it.
    Reply With Quote Edit / Delete Reply United States Show Events Agree Agree x 2 (list)

  13. Post #13
    Gold Member
    gparent's Avatar
    January 2005
    3,949 Posts
    Okay, let's drop the issue of char* being completely different from char[] for now.

    EDIT:

    Okay I get what you mean.

    If what you want to do is modify what a pointer *points to* from another scope, then you pass a pointer to pointer (because the pointer will be passed by value).

    Otherwise, this will happen:

    void modifyPointedTo(int* ptr)
    {
        ptr = (int*) malloc(sizeof(int));
    }
    
    int main()
    {
        int* iPtr;
        modifyPointedTo(iPtr);
        *iPtr = 0;
    } 
    

    ptr gets passed by value, you assign to the copy of iPtr, memory gets leaked, and your pointer is still uninitialized.
    Reply With Quote Edit / Delete Reply Show Events Late Late x 1 (list)

  14. Post #14
    Gold Member
    jA_cOp's Avatar
    May 2006
    2,691 Posts
    In C, if you want to pass a string to a function and have the string be modified and returned without the return statement would you use a double pointer?

    I know char* is the same as char[], so you would pass a char** right?

    So something like this:
    void modify(char** c, char** d)
    {
      *c = strcat(c, "a");
      *d = strcat(d, "b");
    }
    
    Indeed that is what you'd do, except you don't pass a pointer-to-pointer to the strcat function.

    Since char* can be used for strings, it's basically the same as char[].
    So if I wanted to modify the memory allocated to the array, I think I'd have to use a pointer to the array, thus char**. I'm not sure though.
    A pointer to an array is written char* array[], while a pointer-to-pointer is written as char**.

    As arrays can be implicitly cast to pointers, it usually means your code will work the same either way, but you can't dereference an array (without indexing, which can be misleading if it's really just a pointer-to-pointer) without making a pointer out of it first (at which point receiving char** in your function makes more sense).

    Neither can you reassign arrays, as they are constant.
    Reply With Quote Edit / Delete Reply Norway Show Events Informative Informative x 1 (list)

  15. Post #15
    Gold Member
    HubmaN's Avatar
    July 2007
    6,267 Posts
    Since char* can be used for strings, it's basically the same as char[].
    So if I wanted to modify the memory allocated to the array, I think I'd have to use a pointer to the array, thus char**. I'm not sure though.
    That's actually because you only have a dword to push parameters on a stack to a function, so I'm guessing only primitives are really passed by value.

  16. Post #16
    Gold Member
    jA_cOp's Avatar
    May 2006
    2,691 Posts
    That's actually because you only have a dword to push parameters on a stack to a function, so I'm guessing only primitives are really passed by value.
    Everything but arrays is passed by value in C, including structs.

    (And you can allocate more memory on the stack than the processor word size simply by incrementing the stack pointer. If push was the only way to allocate memory on the stack, you'd have some real nasty code for array and struct allocations.)

  17. Post #17
    Gold Member
    HubmaN's Avatar
    July 2007
    6,267 Posts
    Everything but arrays is passed by value in C, including structs.

    (And you can allocate more memory on the stack than the processor word size simply by incrementing the stack pointer. If push was the only way to allocate memory on the stack, you'd have some real nasty code for array and struct allocations.)
    Oh, thanks.
    Explains why some people use pusha and popa instead of doing it manually, I suppose...

  18. Post #18
    Gold Member
    Dr Magnusson's Avatar
    July 2008
    2,695 Posts
    Now that we're on the topic of pointers, could someone please explain how I would derefence a pointer that is member of a struct?

    Like so
    struct a {
        char *b;
    };

  19. Post #19
    Gold Member
    gparent's Avatar
    January 2005
    3,949 Posts
    The same way you dereference anything else.

    *(a.b)

  20. Post #20
    Gold Member
    Dr Magnusson's Avatar
    July 2008
    2,695 Posts
    The same way you dereference anything else.

    *(a.b)
    Ah, cool. This would explain the ridiculous amounts of pointer and value errors in my code. Thank you.

  21. Post #21
    Gold Member
    nullsquared's Avatar
    November 2007
    2,450 Posts
    You don't even need the parenthesis. *a.b is more readable IMO.
    Reply With Quote Edit / Delete Reply United States Show Events Agree Agree x 2 (list)

  22. Post #22
    Gold Member
    gparent's Avatar
    January 2005
    3,949 Posts
    There's a lot of things you don't need in any language, but when it comes down to pointers I try to make things as clear as possible when giving examples.

    EDIT: And honestly I always look up * precedence, it drives me nuts.