3

i'm new to developing with c. sure enough there'd come a day i need your help. And I guess this time is now :)

What I am trying to do: I am experimenting with MySQL Api in C. For that i wanted to use a struct to hold my SQLQuery and all it's params, e.g. user data for selection or inserting.

Then with a couple of functions i wanted to add, remove and compile the string to use it in a query.

To use my createSqlQuery Function i'd like to pass a reference to my SQLQuery Structure into it and change it within the function. After that functions ends it should not go out of scope and still be usable in the main function.

Thats where i am currently stucked. I guess my Problem is pretty simple, but after looking and trying at it for hours i'm kinda blind to see the solution. Using this Question: Passing pointers/references to structs into functions i finally happend to have a working code in the way that the structure is still usable after the create Function ends.

But for some reason i cant compile my code further because it cant assign something to my structure.

Error Message:

main.c:127:10: error: request for member ‘addParam’ in something not a structure or union

This happened after adding a second * in the create function to get a pointer to pointer (see other stackoverflow question).

This is what i have so far:

typedef struct sqlQuery sqlQuery;

struct sqlQuery{
    char *queryS;
    char **params; //array of array of chars to hold the params to replace %? in the query
    bool (*addParam)(sqlQuery*, char*);
    bool (*compile)(sqlQuery*);
};

int main(){
/* ...  */
    sqlQuery *testQuery = NULL;
    printf("%p\n", &testQuery);
    printf("%p\n", testQuery);
    createSqlQuery(&testQuery,"SELECT * FROM test WHERE name = '%?'");
    printf("%p\n", testQuery);
    if (testQuery != NULL) printf("working, testQuery still assigned");
    //testQuery->addParam(testQuery, "test");
    //freeSqlQuery(testQuery);

    exit(EXIT_SUCCESS);
}

bool createSqlQuery(sqlQuery **query, char *queryString){
    *query = (struct sqlQuery *) malloc(sizeof(struct sqlQuery));  //get heapspace for sqlQuery Struct
    printf("%p\n", *query);
    //query->addParam = __sqlQueryAddParam;      //link param function pointer
    //query->compile = __compileSqlQuery;        //link compile function pointer
    *query->queryS = queryString;               //save pointer to query String
    //^^^ this is where the error occurs

    return true;
}

I also tried combinations and variations of:

(sqlQuery *)*query->queryS = queryString;

with **, or &...

I hope you get what i am struggling with, i guess it's simple but i really cant seem to figure it out :)

Thanks in advance!

Community
  • 1
  • 1
Daniel
  • 33
  • 2
  • Can you do a quick sanity check for me and change the `typedef struct sqlQuery sqlQuery; struct sqlQuery { ... };` to just `typedef struct { ... } sqlQuery;` – slugonamission Jun 04 '13 at 13:31
  • [Please don't cast the return value of `malloc()` in C](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – unwind Jun 04 '13 at 13:32
  • Oh yeah, then remove the `struct` from all uses of `struct sqlQuery`. – slugonamission Jun 04 '13 at 13:33
  • slugonamission: you're right. I didn't have them in the first place. later added them to check if they do any difference. unwind: ups :) copied that from the other question... – Daniel Jun 04 '13 at 13:42

4 Answers4

5

This is caused by operator precedence, as the member access operator -> has higher precedence than the dereference operator *. Change:

*query->queryS = queryString; 

to:

(*query)->queryS = queryString;

Other:

  • Don't cast the return value from malloc().
  • The code is assigning the address of a string literal, which is read-only, to a char*. Use const char* or copy the string (using malloc()/strcpy() or strdup() if your implementation provides it.
  • Remember to free() what was malloc()d.
hmjd
  • 120,187
  • 20
  • 207
  • 252
0

For more simplicity try

bool createSqlQuery(struct sqlQuery **ptrresultquery, char *queryString)
{
    struct sqlQuery *query = (struct sqlQuery *) malloc(sizeof(struct sqlQuery));  //get heapspace for sqlQuery Struct

     query->addParam = __sqlQueryAddParam;      //link param function pointer
     query->compile = __compileSqlQuery;        //link compile function pointer
     query->queryS = queryString;               //save pointer to query String

     // write the local pointer back via parameter ptr
     *ptrresultquery= query;

     return true;
}

Otherwise, what you want to do with your syntax is

    (*ptrresultquery)->queryS= queryString;
Nicholaz
  • 1,419
  • 9
  • 11
0

It would be better to have your createSqlQuery() function return the newly created query, that makes it much easier to use in actual code.

But, if you insist on returning boolean and accepting a pointer to pointer, it's easier to work with a temporary pointer inside the function:

bool createSqlQuery(sqlQuery **query, char *queryString){
  struct sqlQuery *q = malloc(sizeof *q);
  if( q != NULL ) {
    q->addParam = __sqlQueryAddParam;
    q->compile = __compileSqlQuery;        //link compile function pointer
    q->queryS = queryString;
    *query = q;
  }
  return q != NULL;
}

Also, make sure about the memory handling for your strings, and avoid symbols that begin with two underscores.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • hi, i started with that as my first idea :) sqlQuery* createSqlQuery(char *queryString){} i changed it so i can easily do an if(!createSqlQuery("...")){/*error handling*/} – Daniel Jun 04 '13 at 13:48
0

(*query)->queryS = queryString; will do the work

And use prototypes if you call a function after main

bool createSqlQuery(sqlQuery **query, char *queryString);
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
  • thank you for that hint. I commented them out in this example! next thing up to learn is how to split those things up into .h and .c and use a working Makefile :) – Daniel Jun 04 '13 at 13:50