Предупреждение при приведении типа между указателем и указателем на функцию - PullRequest
6 голосов
/ 13 октября 2009

Я портирую некоторый код C в среду чипа TI DSP. Я борюсь с компилятором C.

У меня есть структура данных, которая включает указатель на функцию. У меня есть функция, которая инициализирует структуру данных. Примерно так:

typedef void (*PFN_FOO)(int x, int y);

struct my_struct
{
    PFN_FOO pfn;
};

init_struct(struct my_struct *p, void *pfn)
{
    p->pfn = (PFN_FOO)pfn;
}

В Visual Studio и GCC этот вид кода компилируется без жалоб. На самом деле, поскольку аргумент pfn имеет тип void *, мне даже не нужно ставить там приведение; это было бы просто безоговорочно разослано без жалоб.

В Code Composer Studio для чипов TI DSP я получаю «предупреждение: недопустимое преобразование типов»

Моя политика - компилировать мой код без предупреждений, поэтому я хочу это исправить. Я испробовал все виды кастинга. Я обнаружил, что компилятор совершенно счастлив, если сначала приведу свой указатель void * к int, а затем приведу его к правильному типу. Фу, гадость!

Как я могу сделать это приведение без жалоб компилятора? Мне действительно нужно привести к int, чтобы закрыть компилятор?

Примечание: я специально не ищу решение с эффектом "изменить init_struct(), чтобы принять PFN_FOO вместо void *". Это будет работать для этого упрощенного фрагмента кода, но не будет работать для реального кода, который создает список, возможно, разнородных вещей.

Ответы [ 2 ]

12 голосов
/ 13 октября 2009

Стандарт C, в частности, не поддерживает преобразования между указателями на объекты данных и указателями на функции. GCC и Visual Studio поддерживают это как расширение.

Если вы хотите, чтобы ваша функция соответствовала стандартам (но все еще использовать параметр void *), вы можете вместо этого передать указатель на указатель функции. Это работает, потому что сами указатели на функции являются обычными объектами, поэтому указатель на указатель на функцию может быть преобразован в void * очень хорошо:

init_struct(struct my_struct *p, void *pfn)
{
    PFN_FOO *foo = pfn;
    p->pfn = *foo;
}

Затем вызывающая сторона должна создать временный объект PFN_FOO для передачи указателя при вызове:

PFN_FOO fp = &somefunc;
/* ... */
init_struct(p, &fp);
3 голосов
/ 13 октября 2009

Разве ты не пишешь?

typedef void (*PFN_FOO)(int x, int y);

См. учебник .

...