Confused with pointers and pass by reference

This is a discussion on Confused with pointers and pass by reference within the C Programming forums, part of the General Programming Boards category; I never seem to be certain when to use the asterisk or the ampersand. I simply want the "new_mysql_connection" function ...

  1. #1
    Registered User
    Join Date
    May 2012
    Posts
    8

    Confused with pointers and pass by reference

    I never seem to be certain when to use the asterisk or the ampersand. I simply want the "new_mysql_connection" function to set the *conn in the main. So I am passing *conn to the function by reference. What am I doing wrong?

    Code:
    void new_mysql_connection(MYSQL *new_connection){
            char *server = "localhost";
            char *user = "myuser";
            char *password = "mypassword";
            char *database = "mydb";
            new_connection = mysql_init(NULL);
            /* Connect to database */
            if (!mysql_real_connect(new_connection, server,user, password, database, 0, NULL, 0))
            {
                            exit(1);
            }
    }
    
    
    main()
    {
            MYSQL *conn;
            MYSQL_RES *result;
            MYSQL_ROW row;
            int num_fields;
            int i;
    
    
            new_mysql_connection(&conn);
    
    
    
    
            mysql_query(conn, "show tables");
            result = mysql_store_result(conn);
    
    
            num_fields = mysql_num_fields(result);
    
    
            while ((row = mysql_fetch_row(result)))
            {
                    for(i = 0; i < num_fields; i++)
                    {
                            printf("%s ", row[i] ? row[i] : "NULL");
                    }
                    printf("\n");
            }
    
    
            mysql_free_result(result);
            mysql_close(conn);
    }

  2. #2
    Registered User
    Join Date
    Jun 2011
    Posts
    2,361
    This function is expecting a pointer:

    Code:
    void new_mysql_connection(MYSQL *new_connection)
    You declare that type of pointer in "main()":

    Code:
    MYSQL *conn;
    So you should be sending the pointer to that function, not the address of that pointer:

    Code:
    new_mysql_connection(&conn);  // <--- remove the "address-of" operator (&)

  3. #3
    Registered User
    Join Date
    May 2012
    Posts
    8
    Should I change the function to expect an address then? So that I can pass conn as an address...

  4. #4
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,681
    By writing
    Code:
    new_mysql_connection(&conn);
    it is like 'killing' the pointer
    Remember that & 'kills' the *

  5. #5
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,681
    Quote Originally Posted by 50tonrobot View Post
    Should I change the function to expect an address then? So that I can pass conn as an address...
    What is the problem if you pass it as Matticus said?

  6. #6
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    new_mysql_connection expects a pointer to MYSQL.
    conn is a ponter to MYSQL.
    Thus you wouldn't need the & operator and just pass conn (without &).

    The problem is that pointers are also just passed by value. Thus if you change the pointer in the function, the pointer in main isn't changed.
    There are 2 possibilities:
    1) return the changed pointer from the function
    2) rewrite the function so that it expects a pointer to a pointer to MYSQL (MYSQL **new_connection) and pass from main a pointer to conn (&conn). Of course you have to change all uses of new_connection inside the function too (you need to dereference it).

    Bye, Andreas

  7. #7
    Registered User
    Join Date
    Jun 2011
    Posts
    2,361
    Quote Originally Posted by 50tonrobot View Post
    Should I change the function to expect an address then? So that I can pass conn as an address...
    The function already does expect an address - and the pointer you declared in "main()" is the address. So send the pointer (which is an address) and not the address of that pointer (which would be the address of the variable which contains an address).

  8. #8
    Registered User
    Join Date
    May 2012
    Posts
    8
    When I remove the ampersand; I get a segmentation fault at execution.

  9. #9
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,681
    I would focus on line 6.It mays needs an *

  10. #10
    Registered User
    Join Date
    May 2012
    Posts
    8
    I think option two works thanks!

  11. #11
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by std10093 View Post
    By writing
    Code:
    new_mysql_connection(&conn);
    it is like 'killing' the pointer
    Remember that & 'kills' the *
    I think "killing the pointer" is misleading. If you use the & operator you construct a pointer to the object, in this case a pointer to a pointer.
    & and * are complementary: & adds one "pointer level", * reduces one.

    Bye, Andreas

  12. #12
    Registered User
    Join Date
    Jun 2011
    Posts
    2,361
    Code:
    int x;     // integer variable
    int *ptr;  // integer pointer variable
    
    ptr = &x;  // "ptr" is a pointer (to an address), so it should contain an address to point to;
               // the address of 'x' in this case
    
    foo(ptr);  // for function:  void foo(int *pInt);
               // this function wants an integer pointer (which is an address), so we're sending it one;
               // "ptr" already contains the address of 'x'
    
    foo(&x);   // this will do the same exact thing, because "ptr = &x"
               // we're sending it the address of 'x' just like the above example

  13. #13
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,681
    Quote Originally Posted by AndiPersti View Post
    I think "killing the pointer" is misleading. If you use the & operator you construct a pointer to the object, in this case a pointer to a pointer.
    & and * are complementary: & adds one "pointer level", * reduces one.

    Bye, Andreas
    Could you explain a bit more please?With an example perhaps?

  14. #14
    Registered User
    Join Date
    May 2012
    Posts
    8
    This seems to be the solution...

    Code:
    void new_mysql_connection(MYSQL **new_connection){
            char *server = "localhost";
            char *user = "myuser";
            char *password = "mypassword";
            char *database = "mydb";
            *new_connection = mysql_init(NULL);
            /* Connect to database */
            if (!mysql_real_connect(*new_connection, server,user, password, database, 0, NULL, 0))
            {
                            exit(1);
            }
    }
    
    
    main()
    {
            MYSQL *conn;
            MYSQL_RES *result;
            MYSQL_ROW row;
            int num_fields;
            int i;
    
    
            new_mysql_connection(&conn);
    
    
    
    
            mysql_query(conn, "show tables");
            result = mysql_store_result(conn);
    
    
            num_fields = mysql_num_fields(result);
    
    
            while ((row = mysql_fetch_row(result)))
            {
                    for(i = 0; i < num_fields; i++)
                    {
                            printf("%s ", row[i] ? row[i] : "NULL");
                    }
                    printf("\n");
            }
    
    
            mysql_free_result(result);
            mysql_close(conn);
    }

  15. #15
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by std10093 View Post
    Could you explain a bit more please?With an example perhaps?
    Code:
    #include <stdio.h>
    
    int main(void)
    {
        int i, *ptr1, **ptr2, ***ptr3;
    
        i = 10;
        ptr1 = &i;
        ptr2 = &ptr1;
        ptr3 = &ptr2;
    
        printf("%d\n", i == **ptr2);
        printf("%d\n", i == **&ptr1);
        printf("%d\n", *&i == ***ptr3);
        printf("%d\n", &i == **&*&ptr2);
    
        return 0;
    }
    If you can follow, you understand the relationship between * and & :-)

    Basically *&i == i, because & and * cancel. For every & you add to an object, you need a * to get back.

    EDIT: I just want to add that you can't use two adjacent &'s like &&i because & needs a lvalue but returns a rvalue (see this article for a discussion of lvalues and rvalues)

    Bye, Andreas
    Last edited by AndiPersti; 07-11-2012 at 03:28 PM. Reason: additional remark

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 02-14-2012, 06:45 PM
  2. Pass by value/reference
    By Niels_M in forum C Programming
    Replies: 14
    Last Post: 11-07-2010, 12:35 PM
  3. Confused as to how to pass back to main
    By J-Camz in forum C Programming
    Replies: 6
    Last Post: 11-28-2008, 06:21 AM
  4. Pass by reference vs pass by pointer
    By Non@pp in forum C++ Programming
    Replies: 10
    Last Post: 02-21-2006, 12:06 PM
  5. pass be reference versus pass by value
    By Unregistered in forum C++ Programming
    Replies: 2
    Last Post: 08-01-2002, 01:03 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21