Thread: Question regarding pointers

  1. #1
    Registered User
    Join Date
    Sep 2013
    Posts
    16

    Question Question regarding pointers

    Hey guys,

    I have programmed a tree structure with the help of my C++ book and was wondering about the usage of double pointers by the author.

    Here's the code:


    Code:
    #include <iostream>
    #include <malloc.h>
    #include <string>
    using namespace std;
    
    struct link_str{
        string *pbegriff;
        link_str *left;
        link_str *right;
    
    };
    
    void eintragen(link_str **pstart, string s1){
        
        link_str *pliste;
        pliste = *pstart;
    
        //First Case
        if(pliste == NULL){
            pliste = (link_str *)malloc(sizeof(link_str));
    
            
    
            pliste->pbegriff = new string(s1);
            pliste->left = NULL;
            pliste->right = NULL;
    
            *pstart = pliste; 
            return;
        }
        while(pliste != NULL){
            if(s1 <= *(pliste->pbegriff)){
                if(pliste->left != NULL){
                    pliste = pliste->left;
                } else {
                pliste->left =(link_str *)malloc(sizeof(link_str));
                pliste = pliste->left; 
    
                    //Datensatz
                pliste->pbegriff = new string(s1);
                pliste->left = NULL;
                pliste->right = NULL;
    
    
                pliste = NULL; 
                }
            } else {
                if(pliste->right != NULL){
                    pliste = pliste->right; 
                } else {
                    pliste->right =(link_str *)malloc(sizeof(link_str));
                    pliste = pliste->right; 
    
                    
                    pliste->pbegriff = new string(s1);
                    pliste->left = NULL;
                    pliste->right = NULL;
    
    
                    pliste = NULL; //Schleife zu Ende
                }
            }
        }//while(pliste != NULL)
    
    
    }//void eintragen(link_str **pstart, string s1)
    
    void ausgabe(link_str *pliste){
    
        if (pliste == NULL) return;
        ausgabe(pliste->left); //Rekursion
        cout << "Sorted:  " << * (pliste->pbegriff) << endl;
        ausgabe(pliste->right);//Rekursion
    }
    
    void freigeben(link_str *pliste){
        if (pliste == NULL) return;
        freigeben(pliste->left);
        freigeben(pliste->right);
        delete(pliste->pbegriff);
        free(pliste);
    }
    
    int main() {
    
        
    
        
    
        link_str *pstart = NULL; 
    
        string s1;
    
        //Filling the list
        do {
            getline(cin, s1,'\n');
            if(s1 != "QUIT"){
                eintragen(&pstart,s1);
            }
    
        }while(s1 != "QUIT");
    
        //output of the list
    
        ausgabe(pstart);
    
        //Free the list
    
        freigeben(pstart);
        pstart = NULL;
    
    
    
        return 0;
    }

    My question:

    1.Instead of writing eintragen(link_str **pstart,string s1) in line 13 which gets the value (&pstart, s1) in line 98, wouldn't it be enough if I just delete one & and one * and getting this:

    eintragen(link_str *pstart,string s1) which just gets the value (pstart,s1).
    Unfortunately the code doesn't work anymore, if I put it like that.

    (Also, you have to change line 16 and 28 from *pstart to just pstart, as you only have to dereference once.)
    Last edited by Chris L. Tailor; 09-15-2013 at 02:09 AM.

  2. #2
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by Chris L. Tailor View Post
    1.Instead of writing eintragen(link_str **pstart,string s1) in line 19 which gets the value (&pstart, s1) in line 97, wouldn't it be enough if I just delete one & and one *
    The issue is that eintragen(...) updates pstart, so it needs the address of pstart in order to update it.

  3. #3
    Registered User
    Join Date
    Sep 2013
    Posts
    16
    If I leave out the & when transfering pstart and leaving out one *, I am basically just sending the adress, I thought?

    The adress is all it needs to update itself with pliste? The IDE also gives me no errors regarding the type, so I thought that isn't the problem.

    Besides, the program (with leaving out * and &) works until the point, where it comes to output the data, it just terminates at that point.
    Last edited by Chris L. Tailor; 09-15-2013 at 02:35 AM.

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    If the function is to update a pointer, it needs to receive a pointer to pointer and the caller needs to supply the address of a pointer.

    Pointers have two attributes: their value (which is an address) and the type of whatever is at that address. Both have to align.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    If the function is to update a pointer, it needs to receive a pointer to pointer and the caller needs to supply the address of a pointer.

    Pointers have two attributes: their value (which is an address) and the type of whatever is at that address. Both have to align. In your reasoning, you're neglecting the need for the second attribute.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  6. #6
    Registered User
    Join Date
    Sep 2013
    Posts
    16
    So you are saying that
    Code:
    void main{
    int *pointer = NULL;
    
    function (&pointer);
    return 0;
    }
    
    function(int **pointer){
    int* secondpointer;
    secondpointer = *pointer;
    
    [...]
    
    //Update
    
    *pointer = secondpointer;
    
    }
    is not the same as

    Code:
    void main{
    int *pointer = NULL;
    
    function (pointer);
    return 0 ;
    }
    
    
    function(int *pointer){
    int* secondpointer;
    secondpointer = pointer;
    
    [...]
    
    //Update
    
    pointer = secondpointer;
    
    }
    I don't see where the problem is, in both cases secondpointer receives the adress of pointer, where do you see the information leak, that it doesn't work anymore?
    My idea is kinda like this:

    &pointer-->**--->*pointer

    pointer--->*--->*pointer

    Arguing that & and * eliminate each other anyway, so why bother writing them in the first place?
    Last edited by Chris L. Tailor; 09-15-2013 at 03:21 AM.

  7. #7
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    The goal here is for the function to change the value of pointer in main(). Take the simpler case of a integer:

    Code:
    void function(int *x)
    {
        *x = 123;
    }
    
    int main()
    {
        int i = 456;
        function(&i);
        return(0):
    }
    The same logic applies when trying to have function() update any parameter passed to function, main() has to pass the address of the variable, so that the function can update the variable, even when that variable is a pointer.

  8. #8
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Chris L. Tailor View Post
    So you are saying that
    Code:
    void main{
    int *pointer = NULL;
    
    function (&pointer);
    return 0;
    }
    
    function(int **pointer){
    int* secondpointer;
    secondpointer = *pointer;
    
    [...]
    
    //Update
    
    *pointer = secondpointer;
    
    }
    is not the same as

    Code:
    void main{
    int *pointer = NULL;
    
    function (pointer);
    return 0 ;
    }
    
    
    function(int *pointer){
    int* secondpointer;
    secondpointer = pointer;
    
    [...]
    
    //Update
    
    pointer = secondpointer;
    
    }
    That's exactly what I'm saying. Although the difference is subtle, and you won't spot it in your particular test case. The problem is not the value that secondpointer receives in the function. It is the assignment you do to pointer (or *pointer) that works differently - but your test case does not detect that.

    Try comparing these two.
    Code:
    #include <stdio.h>
    void function(int **);   /*  Don't rely on the compiler inferring the function argument */
    
    int main    /*  main() returns int, not void */
    {
        int *pointer = NULL;
     
        function (&pointer);
        printf("pointer is %s\n", (pointer == NULL ? "NULL" : "not NULL"));
        return 0;
    }
     
    void function(int **pointer)
    {
         static int x;
         *pointer = &x;
    }
    and
    Code:
    #include <stdio.h>
    void function(int *);
    
    int main    /*  main() returns int, not void */
    {
        int *pointer = NULL;
     
        function (pointer);
        printf("pointer is %s\n", (pointer == NULL ? "NULL" : "not NULL"));
        return 0;
    }
     
    void function(int *pointer)
    {
         static int x;
         pointer = &x;
    }

    I've restructured relative to your code to avoid using anachronisms that have been deprecated since 1989. This is 2013, and there is little value in your using error-prone techniques in new code that have been obsolete for over 20 years. Don't rely on the compiler inferring what arguments your function accepts - tell it - and don't rely on functions returning int if you leave that out.

    Also, main() returns int, not void. That has been true since Brian Kernighan and Dennis Ritchie created C.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  9. #9
    Registered User
    Join Date
    Sep 2013
    Posts
    16
    I think I understand now, in your second example, the pointer is not updated, because you just change the value of the local pointer, by giving it the value of the x, but it doesn't affect the value(with the adress to null) in the main-function, is that correct?

    To update anything you'll have to use a pointer in the function, just switching the adress isn't enough, correct?

  10. #10
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Chris L. Tailor View Post
    I think I understand now, in your second example, the pointer is not updated, because you just change the value of the local pointer, by giving it the value of the x, but it doesn't affect the value(with the adress to null) in the main-function, is that correct?
    More or less. Any change to the value of an argument within a function are not visible to the caller.

    Quote Originally Posted by Chris L. Tailor View Post
    To update anything you'll have to use a pointer in the function, just switching the adress isn't enough, correct?
    That'll do, more or less.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    What book are you using? You should be using new and not malloc. Using malloc here will cause undefined behaviour.
    As an alternative to pointers to pointers, you can also simply use a reference to the pointer.
    I'm afraid that your code is all C rather than C++, save for using a few C++ containers.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Elysia View Post
    What book are you using? You should be using new and not malloc. Using malloc here will cause undefined behaviour.
    I agree that mixing the usage of malloc() and operator new, as occurs in this example, is less than a good idea. However the usage here doesn't cause undefined behaviour.

    malloc() and free() are being used to allocate/deallocate a POD struct that contains pointers, operator new and delete are being used to allocate/deallocate a C++ type with non-trivial constructor/destructor, and the order of things are not confused.

    Not exactly a journey of delight for future maintainers, and pretty poor style, but the behavior is well defined.

    To the OP though: Elysia's comment about mixing C and C++ is valid. That code is a hybrid, which is not good style in either C or C++.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by grumpy View Post
    I agree that mixing the usage of malloc() and operator new, as occurs in this example, is less than a good idea. However the usage here doesn't cause undefined behaviour.
    You're right. I missed that only pointers used as opposed to storing the objects directly. My bad.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Registered User
    Join Date
    Sep 2013
    Posts
    16
    Thank you all for the many responses.
    Well, the author used that C/C++ hybrid style, no idea why he did it, but I'll stick to C++ from now on.

    Got another issue regarding overloading operators, (the variables are german language , it's basically just adding some class attributes of two objects)
    It basically doesn't work, c1 just stays like it is, and isn't added with c2.
    The operator isn't syntax-highlighted anymore when I write a + behind it, that's why I think it could be a problem with the compiler.
    But maybe I just made a mistake somewhere, maybe it works with your compiler?


    Code:
    //============================================================================
    // Name        : Operatorenueberladen.cpp
    // Author      : 
    // Version     :
    // Copyright   : Your copyright notice
    // Description : Hello World in C++, Ansi-style
    //============================================================================
    
    #include <iostream>
    using namespace std;
    
    class stellarobjekt{
    
        double laenge, breite, hoehe;
    
    public:
    
        stellarobjekt(int laenge, int breite, int hoehe){
            this->laenge= laenge;
            this->breite =breite;
            this->hoehe = hoehe;
    
        }
    
        stellarobjekt operator+ (stellarobjekt sto){
            stellarobjekt tmp = (*this);
            tmp.laenge += sto.laenge;
            tmp.breite += sto.breite;
            tmp.hoehe += sto.hoehe;
            return (tmp);
        }
    
        void ausgabe(){
            cout << laenge << "  " << breite << "  " << hoehe << endl;
        }
    
    };
    
    
    int main() {
    
        stellarobjekt c1(300, 400, 500);
        stellarobjekt c2(500, 700, 8000);
    
        c1.ausgabe();
        c2.ausgabe();
    
    
    
        c1 = c1 + c2;
    
        c1.ausgabe();
    
    
        return 0;
    }

  15. #15
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    It works for me.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Question about pointers.
    By november1992 in forum C Programming
    Replies: 4
    Last Post: 09-01-2012, 04:05 PM
  2. Replies: 7
    Last Post: 05-19-2010, 02:12 AM
  3. A question on pointers
    By Niels_M in forum C Programming
    Replies: 20
    Last Post: 08-27-2009, 08:05 AM
  4. Pointers to pointers question
    By mikahell in forum C++ Programming
    Replies: 10
    Last Post: 07-22-2006, 12:54 PM
  5. Pointers Question.....Null Pointers!!!!
    By incognito in forum C++ Programming
    Replies: 5
    Last Post: 12-28-2001, 11:13 PM