Thread: Problem Passing Structure Reference To Function

  1. #1
    Registered User
    Join Date
    Apr 2010
    Posts
    15

    Problem Passing Structure Reference To Function

    I have a structure declared like:

    Code:
    typedef struct _sqlite {
            int rc; 
            int ncol;
            int nrow;
            char *db_name;
            sqlite3 *db;
            sqlite3_stmt *stmt;
            char *query; 
            int db_status;
    } SQL_handle;
    I initialize the structure with this function:

    Code:
    int init_sql_handle(SQL_handle **handle)
    {
            SQL_handle *new;
    
            new = safemalloc(sizeof(SQL_handle));
    
            if(!new) {
                    fprintf(stderr, "Couldn't allocate sql init memory, terminating!\n");
                    exit(255);
            }
    
            new->query = safestrdup("SELECT main.id, artists.artist, main.title, main.remixer, \
                            labels.label, main.year, genres.genre, main.proj, main.mark, classes.class, \
                            main.class_no from main, artists, genres, labels, classes WHERE \ 
                            main.artist=artists.artist_id AND main.label=labels.label_id AND \
                            main.genre=genres.genre_id AND main.class=classes.class_id LIMIT 20;");
    
            new->db_name = safestrdup("music.db");
    
            new->nrow = 0;
    
            new->rc = new->ncol = new->nrow = new->db_status = 0;
    
            *handle = new;
    }
    My function to open the database with the structure is:

    Code:
    int open_db(SQL_handle **handle)
    {
            handle->rc = sqlite3_open(handle->db_name, &handle->db);
    
            if(handle->rc) {
                    /* Print a pop-up screen for error. */
                    handle->db_status = close_db(handle->db);
                    exit(1);
            }
    
            return 0;
    }
    My function to prepare the db statement is:

    Code:
    int prepare_db(SQL_handle **handle)
    {
            const char *tail;
    
            /* Does not affect the connection or database in any way.
             * It does not start a transaction or get a lock. 
             * Ref: The Definitive Guide To SQL_handle, p. 216 */
            handle->rc = sqlite3_prepare(handle->db, handle->query, strlen(handle->query), &handle->stmt, &tail); 
    
            if(handle->rc != SQLITE_OK) {
                    /* TODO: Handle error in db. */
                    exit(1);
            }
    
            return 0;
    }
    In main I call all three functions (in this order) like:

    Code:
    init_sql_handle(&handle);
    
    open_db(&handle);
            
    prepare_db(&handle);
    ...after creating the handle above main...

    Code:
    SQL_handle *handle = NULL;
    When I compile, though, I get these errors:

    Code:
    gcc -g3 -c main.c 
    gcc -g3 -c color.c 
    gcc -g3 -c print.c 
    gcc -g3 -c tree.c 
    gcc -g3 -c window.c 
    gcc -g3 -c sql.c 
    sql.c: In function 'open_db':
    sql.c:33: error: request for member 'rc' in something not a structure or union
    sql.c:33: error: request for member 'db_name' in something not a structure or union
    sql.c:33: error: request for member 'db' in something not a structure or union
    sql.c:35: error: request for member 'rc' in something not a structure or union
    sql.c:37: error: request for member 'db_status' in something not a structure or union
    sql.c:37: error: request for member 'db' in something not a structure or union
    sql.c: In function 'prepare_db':
    sql.c:51: error: request for member 'rc' in something not a structure or union
    sql.c:51: error: request for member 'db' in something not a structure or union
    sql.c:51: error: request for member 'query' in something not a structure or union
    sql.c:51: error: request for member 'query' in something not a structure or union
    sql.c:51: error: request for member 'stmt' in something not a structure or union
    sql.c:53: error: request for member 'rc' in something not a structure or union
    make: *** [sql.o] Error 1
    What am I doing wrong here??? I thought that I was to pass in a reference to the struct so that it could be modified. I could put these back into main but I wanted to use a function instead so I don't keep having to write the error checking.

    Also, in prepare_db and open_db, in sqlite3_prepare and sqlite3_open, how would I pass those parameters that require a reference to stmt and db? I passed the structure as a reference anyways. Thank you.

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    How about:
    Code:
    if((*handle)->rc != SQLITE_OK)
    A pointer to a pointer is not the same thing as a pointer to a structure.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Apr 2010
    Posts
    15
    Thanks MK27. I don't completely understand, but, it compiled without errors now.

    Whenever I pass a structure by reference to a function I should always use the (*struct)->member notation?

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You can use -> on a pointer-to-a-structure to access the members pointed to. Had you passed the structure by "reference" (i.e. by pointer), your function prototype would have looked like
    Code:
    int open_db(SQL_handle *handle)
    Instead, you passed a pointer to a pointer to a structure, so you need to dereference once (i.e., put a * on it) just to get back to a pointer to a structure.

  5. #5
    Registered User
    Join Date
    Apr 2010
    Posts
    15
    OK. As I understand, if I just want to access the values (not modify them), I pass by reference. If I want to modify the values, I pass a pointer to a pointer to a structure (I thought that was passing by reference)? If I pass a pointer to a pointer to a structure in a function, what if I want just to use (not modify) the value of a member? Would the correct way still be to use (*struct)->handle to see the value? Thanks for your help.
    Last edited by soj0mq3; 04-24-2010 at 10:09 AM. Reason: I thought the quote tag was for "".

  6. #6
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by soj0mq3 View Post
    Whenever I pass a structure by reference to a function I should always use the (*struct)->member notation?
    As tabstop says, you are not passing a reference (pointer) to a structure. You are passing a reference to a reference to a structure (we should really stick to the word "pointer" here tho).

    You don't really need to do that with structs as long as you are assigning only to a struct member, and not the struct pointer itself. Eg,
    Code:
    int open_db(SQL_handle **handle)
    {
            handle->rc = sqlite3_open(handle->db_name, &handle->db);
    
            if(handle->rc) {
                    /* Print a pop-up screen for error. */
                    handle->db_status = close_db(handle->db);
                    exit(1);
            }
    
            return 0;
    }
    The lines in green are assignments, but they are assignments to member of handle. So this:
    Code:
    SQL_handle *myhand = [blahblah]
    int open_db(SQL_handle *handle);  // better
    open_db(myhand);
    Will work as long as you don't reassign "handle" itself in open_db. Make sense?
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    In other words, init_sql_handle is the only one that needs to change the value of the handle itself (because it's creating a new structure), so it needs to pass the handle by "reference", not the structure. The others are modifying the structure, not the handle, so you pass just-the-handle, because the handle is the "reference" to the structure. (We want to pass the structure by reference, not the handle.)

  8. #8
    Registered User
    Join Date
    Apr 2010
    Posts
    15
    I think so. I made your changes and my code works. So my init function is fine the way it is because I'm assigning to the pointer itself? When it's like my init function, that's really the only time I need to pass a pointer to a pointer to a structure? Thanks.

  9. #9
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Yep.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  10. #10
    Registered User
    Join Date
    Apr 2010
    Posts
    15
    OK, thanks. I've got it now. I really appreciate this help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Library troubles with makefile
    By mslate in forum Linux Programming
    Replies: 17
    Last Post: 07-23-2009, 04:43 PM
  2. problem getting structure to work in my function
    By Tom Bombadil in forum C Programming
    Replies: 18
    Last Post: 05-28-2009, 09:53 AM
  3. Undefined Reference Compiling Error
    By AlakaAlaki in forum C++ Programming
    Replies: 1
    Last Post: 06-27-2008, 11:45 AM
  4. Passing structure data to a function?
    By diddy02 in forum C Programming
    Replies: 8
    Last Post: 08-17-2002, 04:15 PM
  5. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM