Thread: A question about pointers in C

  1. #1
    Registered User
    Join Date
    Jun 2009
    Posts
    6

    A question about pointers in C

    Hi everybody, when reading and testing the source code of a program I had a question about pointers and addresses.

    My OS is Ubuntu 8.04. The program I am talking about is SQLite ODBC driver (and its source code can be downloaded from here). However, to understand my problem, it is not important to know what this program does. I just want to ask about the way it used pointers in its source code.

    Basically the source code of this program consists of 2 files: sqliteodbc.c and sqliteodbc.h. Inside sqliteodbc.h it defines a struct like this:

    Code:
    typedef struct {			
        int ov3;			
    } ENV;
    and a type like this:

    Code:
    typedef void * 	SQLHENV;
    And then inside sqliteodbc.c it has 2 important functions, and the code of the 2 functions is as follow:

    The first one is:

    Code:
    SQLAllocHandle(SQLHENV *env)
    {
    ENV *e;
    e = (ENV *) malloc(sizeof (ENV));
    *env = (SQLHENV) e;
    }
    And the second one is:

    Code:
    SQLSetEnvAttr(SQLHENV env)
    {
    ENV *e;
    e = (ENV *) env;
    e->ov3 = 1;
    }
    Then other functions in sqliteodbc.c can obtain the value of ov3 just by being passed to the parameter env. I means they only know the address the void pointer points to, and then they typecast it to ENV*, and then they can access its member, something like this:

    Code:
    foo (SQLHENV env)
    {
    ENV *e;
    e = (ENV *) env;
    if (e->ov3 == 1)
    /*do something here*/
    }
    That is the way functions in sqliteodbc.c 'communicate'. And I think it is quite easy to understand.

    However, when I tried to reproduce this communication mechanism, I failed.

    After being built, this program will be a library, libsqliteodbc.so, and by linking to this library you can use its functions in your code. So I wrote a simple test code like this:
    Code:
    #include "sqliteodbc.h"
    
    main() {
    
       SQLHENV env;
       ENV *ptest;
       
       SQLAllocHandle(&env);
    
       SQLSetEnvAttr(env);
       
       ptest = (ENV *) env;
       
       printf("%d\n", ptest->ov3);
     	
    }
    I expected the output from the above printf command would be '1', but it would not. Could you please explain to me why I did not get the value '1'?

    Thanks in advance!
    Last edited by Kilua; 06-05-2009 at 01:51 AM.

  2. #2
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    What that library is doing is a common occurance in C. A void pointer is typedef'd to some name, and then used as a generic handle to hide the actual data structure implementation. I personally do not like this technique since it prevents type safety checking. A much better way is to forward declare a structure in the header file, and leave its implementation in the C file. This provides the same effect of hiding the implementation, but it also provides type checking.

    Anyways, on to your question. The reason your code doesn't work as expected is probably due to it not knowing what a ENV is. ENV is a type that is hidden (not defined in sqlite3odbc.h), and therefore it cannot be used just by including the header file. You need to also provide the definition of ENV in that header file (which would defeat the purpose of hiding its implementation in the first place).

  3. #3
    Registered User
    Join Date
    Jun 2009
    Posts
    6
    Thank you very much for your answer!

    Quote Originally Posted by bithub View Post
    What that library is doing is a common occurance in C. A void pointer is typedef'd to some name, and then used as a generic handle to hide the actual data structure implementation. I personally do not like this technique since it prevents type safety checking. A much better way is to forward declare a structure in the header file, and leave its implementation in the C file. This provides the same effect of hiding the implementation, but it also provides type checking.
    Yes, before posting this question I also guessed that the author used void* pointers to hide the actual data structure implementation.

    Quote Originally Posted by bithub View Post
    Anyways, on to your question. The reason your code doesn't work as expected is probably due to it not knowing what a ENV is. ENV is a type that is hidden (not defined in sqlite3odbc.h), and therefore it cannot be used just by including the header file. You need to also provide the definition of ENV in that header file (which would defeat the purpose of hiding its implementation in the first place).
    I am sorry, it was a typo, the file I included is sqliteodbc.h. And I managed to compile and run the test code. The program did not encounter any error, but it did not produce the result I expected either.
    Last edited by Kilua; 06-05-2009 at 01:52 AM.

  4. #4
    Registered User
    Join Date
    Jun 2009
    Posts
    6

    Problem is solved!

    I have just obtained the answer from the author of the program, and my problem is solved.

    Briefly the problem is not related to the C programming language, and what I did in the first post of this thread was correct. The problem was caused by another program, which was also involved in the memory allocation process.

    Thank you for reading my topic!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Array pointers question?
    By ben2000 in forum C Programming
    Replies: 4
    Last Post: 07-26-2007, 01:31 AM
  2. A question on Pointers & Structs
    By FJ8II in forum C++ Programming
    Replies: 4
    Last Post: 05-28-2007, 10:56 PM
  3. simple pointers question
    By euphie in forum C Programming
    Replies: 4
    Last Post: 05-25-2006, 01:51 AM
  4. Very stupid question involving pointers
    By 7smurfs in forum C Programming
    Replies: 6
    Last Post: 03-21-2005, 06:15 PM
  5. Quick Question Regarding Pointers
    By charash in forum C++ Programming
    Replies: 4
    Last Post: 05-04-2002, 11:04 AM