несовместимое назначение типа указателя при использовании указателя функции - PullRequest
0 голосов
/ 02 июля 2018

Я пытаюсь использовать указатель функции в моем коде, код такой, как показано ниже.

#include <stdio.h>
#include <pthread.h>

typedef void (*PFUNC)(int);

typedef struct tag_FUNC_INFO_S
{
    PFUNC callback;
    int   index;
} FUNC_INFO_S;

PFUNC callback_print(int index)
{
    printf("[callback] index = %d\n", index);
    return NULL;
}

void thread_test(FUNC_INFO_S *info)
{
    info->callback(info->index);

    pthread_exit(NULL);
}

int main()
{
    pthread_t tid;

    FUNC_INFO_S info;
    info.callback = callback_print;
    info.index    = 777;

    pthread_create(&tid, NULL, (void *)thread_test, &info);

    printf("main printing\n");

    return 0;
}

После компиляции кода с помощью "gcc -Wall xxx.c -o xxx -lpthread" компилятор выдает следующее сообщение:

func_ptr_test.c: 30: 16: предупреждение: несовместимые типы указателей, назначаемые для 'PFUNC' (он же void () (int) ') из' PFUNC (int) '(он же void () (int)) (int) '[-Wincompatible-pointer-types] info.callback = callback_print;

Но, если я изменю код с

info.callback = callback_print;

до

info.callback = (PFUNC)callback_print;

Предупреждающих сообщений больше не появляется. Но даже без приведения типов я думаю, что у «info.callback» тот же тип, что и у «callback_print», поэтому мне интересно, почему появляется предупреждение. У кого-нибудь есть идеи по этому поводу?

Ответы [ 2 ]

0 голосов
/ 03 июля 2018

Иногда изучение того, что находится под поверхностью, помогает лучше понять картину.

В C вы можете в значительной степени рассматривать имя функции как указатель на эту функцию. Взгляните на пример ниже

#include <stdio.h>

int main() {
    (*printf)("test\n");
    return 0;
}

В приведенном выше фрагменте кода мы могли бы просто использовать printf() вместо (*printf)(), и на самом деле это обычный способ вызова функции.

Другим примером является библиотечная функция signal () (да, я пользователь FreeBSD), чье определение дано как

 void
 (*signal(int sig, void (*func)(int)))(int);

Когда вы звоните signal(), конвенция будет

void
handle(int sig)
{
    ...
}

int main(int argc, char **argv)
{
    (void) signal(SIGUSR1, handle);
    ...
}

Теперь, вы можете увидеть трюк здесь? Хотя объявлено, что signal() принимает void (*func)(int) (т. Е. Указатель на функцию, возвращающую void и принимающую единственный аргумент int), мы передаем имя функции этого типа в качестве второго аргумента signal().

Возвращаясь к вашему вопросу, PFUNC - это псевдоним для указателя на функцию, возвращающую void и принимающую единственный аргумент int. Объявляя callback как PFUNC callback, вы говорите своему компилятору, что переменная callback будет указывать на функцию, которая возвращает void и принимает один аргумент int.

Итак, вы должны иметь

void callback_print(int index) /* now you have a void ()(int) */
{
    printf("[callback] index = %d\n", index);
}

, чтобы соответствовать ожидаемому значению вашего задания, выполненного info.callback = callback_print;.

0 голосов
/ 02 июля 2018

Вы не можете определить функцию с указателем функции typedef. Вам просто нужно определить функцию для соответствия typedef:

void callback_print(int index)
{
    printf("[callback] index = %d\n", index);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...