Приведение указателей на функции с различными типами указателей в качестве аргумента - PullRequest
6 голосов
/ 28 января 2012

Следующий код, я думаю, описывает то, что я пытаюсь сделать. В частности, я хочу привести указатель функции к универсальному типу функции, с той лишь разницей в сигнатуре, что это разные типы указателей.

Теперь я знаю, что существует требование, чтобы указатели функций были совместимыми , как обсуждалось в этом вопросе , но я не уверен, имеет ли аргумент разные Тип указателя удовлетворяет этому требованию совместимости.

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

#include <stdio.h>

int float_function(float *array, int length)
{
    int i;
    for(i=0; i<length; i++){
        printf("%f\n", array[i]);
    }
}

int double_function(double *array, int length)
{
    int i;
    for(i=0; i<length; i++){
        printf("%f\n", array[i]);
    }
}


int main() 
{
    float a[5] = {0.0, 1.0, 2.0, 3.0, 4.0};    
    double b[5] = {0.0, 1.0, 2.0, 3.0, 4.0};

    int (*generic_function)(void*, int) = NULL;

    generic_function = &float_function;
    generic_function(a, 5);

    generic_function = &double_function;
    generic_function(b, 5);

    return 0;
}

Ответы [ 3 ]

5 голосов
/ 28 января 2012

ИМХО самый чистый способ выполнить приведение внутри функции.Это приведет к тому, что все сигнатуры функций будут одинаковыми, и исключит приведение коду вызывающего абонента.(это, например, так, как этого хочет qsort ())

int double_function(void *p, unsigned size)
{
    double *array = p    
    unsigned uu;

    for(uu=0; uu < size; uu++){
        printf("%f\n", array[uu]);
    }
return 42;
}
2 голосов
/ 28 января 2012

Да, объявить это без прототипа.

int (*generic_function)() = NULL;

Теперь вы можете назначить любую функцию, которая возвращает int, но также может передавать любой аргумент, и компилятору не требуется отклонять несовместимые аргументы.

1 голос
/ 28 января 2012

EDIT: как указывает @Mat, чтобы следовать спецификации C, вам нужно привести указатель функции обратно к исходному типу, прежде чем вызывать его, что сделало бы весь этот тренинг немного менее полезным;

((int(*)(float*,int))generic_function)(a, 5);

Другое решение (вдохновленное ответом @wildplasser) состоит в том, чтобы обернуть функции в функции, взяв void *, и вместо этого выполнить приведение к этому параметру.Сделать это «по макросам» довольно просто:

#define WRAP(FN, TYPE) int FN##_wrapped(void* p, int len) { return FN((TYPE*)p, len); }
WRAP(float_function, float)
WRAP(double_function, double)

Тогда вы можете использовать вместо этого следующие довольно чистые строки:

generic_function = float_function_wrapped;
generic_function(a, 5);

При этом приведение указателей обычно не является решениемЯ бы выступил, но у него есть свои варианты использования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...