JMcMinn
JMcMinn

Reputation: 275

Invalid type argument / incompatible pointer type C

I know questions of this form have been asked before, but I'm having difficulty finding one that suits my situation.

As someone trying to get used to C, I'm having issues with pointers, specifically Strings. I have a small number of errors that keep cropping up, and I can't wrap my head around what I keep doing wrong.

I'm writing a program that will read username:password key/values and then compare them against given values. For that, I use a userpass struct:

typedef struct {
char user[BUF_MAX];
char pass[BUF_MAX];
} userpass;

And the following code:

char *authThread(char *filename, char *request){

List_t logins;
char user[BUF_MAX];
char pass[BUF_MAX];
char *saveptr = NULL;
char *listptr = NULL;

char *username = strtok_r(request, ":", &saveptr);
char *password = strtok_r(NULL, ":", &saveptr);

char *failCode = malloc(sizeof (char)*BUF_MAX);
sprintf(failCode, "0:%s:0", username);

char *successCode = malloc(sizeof (char)*BUF_MAX);
sprintf(successCode, "1:%s:%s", username, ticketSecret);

if (List_init(&logins)){

  //Retrieve all the user:pass pairs from the auth file
  FILE *fp = fopen(filename, "r");
  while(fscanf(fp, "%s:%s", user, pass) != EOF){
    userpass new;
    //PROBLEM LINES BELOW+++++++++++++++++++++++++++++++++
    strcpy(new->user, user);
    strcpy(new->pass, pass);
    List_add_tail(&logins, &new);
  }//while
  fclose(fp);

  //See if the username/pass combination provided exists in the auth file
  for (;;){
    userpass *next = NULL;
    //PROBLEM LINE BELOW+++++++++++++++++++++++++++++++++
    List_next_node(&logins, &listptr, &next);
    if (next == NULL) break;

    //Match found, return required auth string
    if (strcmp(next->user, username) == 0 && strcmp(next->pass, password) == 0){
      return successCode;
    }//if
  }//for

  return failCode;

}//if
else{
  printf("Error creating auth list\n");
}//else

}//authThread

List_t is a linked list implementation. The header of the List_next_node function is this:

int List_next_node ( List_t *list, void **context, void **data );

I've labelled the two lines where I get an error above. When I try to compile, I get two errors. On the first two lines, I get: invalid type argument of â->â.

One the second line, I get: passing argument 2(3) of âList_next_nodeâ from incompatible pointer type

I can see that both of these issues are caused by variables not being the correct type, but I can't see how that's possible. In the first case, new->user should be a char array, as should user.

In the second case, List_next_node accepts three parameters; a pointer to a list, a pointer to a context pointer, and a pointer to a data pointer. As far as I can tell, everything is the type it should be. I can only imagine it's some problem with how Strings (i.e. char arrays) work in C.

Upvotes: 0

Views: 573

Answers (2)

Garee
Garee

Reputation: 1284

Error 1

You have defined the variable new as a userpass structure yet you access its internal attributes like a pointer.

userpass new;
...
strcpy(new->user, user); // new->user is equivalent to (*new).user
strcpy(new->pass, pass);

Instead, use the . operator:

strcpy(new.user, user);
strcpy(new.pass, pass);

You should dynamically allocate your userpass structures so that they do not go out of scope.

Error 2 (It's a warning)

Your argument &listptr is of type char ** yet the function is expecting void **. You can cast the argument to remove the warning:

 List_next_node(&logins, (void **) &listptr, (void **) &next);

Similarly, &next is userpass ** and it is expecting void **

Upvotes: 1

simonc
simonc

Reputation: 42175

new is declared locally on the stack. It is not a pointer so you need to change

userpass new;
strcpy(new->user, user);
strcpy(new->pass, pass);

to

userpass new;
strcpy(new.user, user);
strcpy(new.pass, pass);

Depending on the implementation of List_add_tail (I can't see it in your question), this may not be the only problem. new goes out of scope after List_add_tail returns so, unless adding an item to the list takes a copy, the list will be left with a pointer to memory that is liable to be reused.

If List_add_tail doesn't create a copy of the userpass* in its second argument, you should change your code to something like

userpass* new = malloc(sizeof(*new));
strcpy(new->user, user);
strcpy(new->pass, pass);
List_add_tail(&logins, &new);

(Note that in this last example, new is a pointer so we have to use the dereference operator -> to access its members again.)

Upvotes: 1

Related Questions