2013-06-10 4 views
0

Я знаю, что вопросы этой формы были заданы раньше, но мне трудно найти тот, который подходит для моей ситуации.Недопустимый аргумент типа/несовместимый указатель типа C

Как кто-то пытается привыкнуть к C, у меня возникают проблемы с указателями, в частности с Строками. У меня есть небольшое количество ошибок, которые продолжают возникать, и я не могу окутать голову в то, что я продолжаю делать неправильно.

Я пишу программу, которая будет читать имя пользователя: пароль/значения, а затем сравнивать их с заданными значениями. Для этого я использую UserPass-структуру:

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

и следующий код:

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 является реализацией связанного списка. Заголовок функции List_next_node заключается в следующем:

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

Я пометил две строки, где я получаю ошибку выше. Когда я пытаюсь скомпилировать, я получаю две ошибки. На первых двух строках я получаю: invalid type argument of â->â.

Одна вторая линия, я получаю: passing argument 2(3) of âList_next_nodeâ from incompatible pointer type

Я могу видеть, что обе эти проблемы вызваны переменными не является правильным типом, но я не могу понять, как это возможно. В первом случае new->user должен быть массивом символов, как и user.

Во втором случае List_next_node принимает три параметра; указатель на список, указатель на указатель контекста и указатель на указатель данных. Насколько я могу судить, все должно быть таким, каким оно должно быть. Я могу только представить себе, что это проблема с тем, как работают строки (то есть массивы символов).

ответ

1

new объявляется локально в стеке. Это не указатель, так что вы должны изменить

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

в

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

В зависимости от реализации List_add_tail (я не могу видеть его в вашем вопросе), это может быть не единственной проблемой , new выходит из области видимости после того, как List_add_tail возвращает так, что если добавление элемента в список не приведет к копированию, список останется с указателем на память, который может быть повторно использован.

List_add_tail Если не создает копию userpass* во втором аргументе, вы должны изменить свой код, чтобы что-то вроде

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

(Заметим, что в этом последнем примере, new указатель таким образом, мы имеем использовать оператор разыменовывания -> для доступа к его членам снова.)

+0

это выглядит как 'userpass' тип данных – tay10r

+0

@TaylorFlores Да, это ЬурейеЕ для struct, показанный чуть выше кода в вопросе – simonc

+0

Я просто не видел тип данных, использованный ранее, выглядит странно. Разве это не '' C++'? Edit: nevermind, подсветка синтаксиса меня сбила с толку. – tay10r

1

Ошибка 1

Вы определили переменную new как структура пользовательского интерфейса, но вы получаете доступ к его внутренним атрибутам, как указатель.

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

Вместо этого используйте . оператор:

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

Вы должны динамически выделять свои UserPass структуры так, что они не выходят за рамки.

Ошибка 2 (Это предупреждение)

&listptr Ваш аргумент имеет тип char ** пока функция ожидает void **. Вы можете привести аргумент, чтобы убрать предупреждение:

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

Аналогично, &next является userpass ** и ожидает void **

+0

Спасибо за ответ! Это покрывает то, что simonc's doesn't - кастинг для void ** - но, к сожалению, я могу принять только один ответ XP. Возможно, они должны быть отредактированы вместе. – JMcMinn

Смежные вопросы