Другие отметили, что вы не можете выполнять это приведение (строго говоря, приведение к void*
что-либо, использующее reinterpret_cast
, также не разрешено, но компиляторы молча допускают. static_cast
предназначено для использования здесь).
Я обычно делаю следующее, что делает каламбур, и это рекомендуемый способ сделать это, в соответствии с man-страницей dlopen
(которая предназначена для выполнения обратного чтения из void*
до указатель функции). Взяв адрес указателя функции, вы получите указатель на данные: указатель на указатель на функцию. Это позволит вам привести его к void*
. Он делает вид, что указывает на void*
(вместо указателя функции), а затем читает его.
Test* (*pF)(void **a);
void *p = *(void**)(void*)&pF;
Промежуточное приведение к void*
делает его эквивалентным использованию двух static_cast
внутри, и заставляет GCC молчать об предупреждении о типе каламбура. При использовании приведения в стиле C ++ это выглядит как комбинация двух static_cast
void *p = *static_cast<void**>(static_cast<void*>(&pF));
Я обнаружил, что, используя эту технику, GCC автоматически замечает, когда левый и правый типы различаются по размеру, и выдает предупреждение в этом случае. Излишне говорить, что, как и во всех методах, которые пытаются обойти это ограничение, это неопределенное поведение.
Если у вас есть функция, и вы хотите void*
, указывающую на нее, вы можете сделать все это в одной строке, но это немного громоздко в синтаксисе. Вот как это можно сделать, но я не рекомендую его, если у вас есть проблемы с его чтением - вы можете использовать его внутри макроса
// using the function declaration you provided
Test** pF(void **a);
void *p = *(void**)(void *) &(Test** (* const&)(void **a))&pF;
Хитрость для того, чтобы начать иметь возможность делать тип, но состоит в том, чтобы преобразовать временный указатель на функцию в lvalue-ссылку на const, которую вы можете взять по адресу, и затем продолжить, как описано выше.
При использовании явного приведения в стиле C ++ static_cast
приведение выглядит намного сложнее, потому что нужно учитывать постоянство. Приведение в стиле C автоматически с этим справляется. Веселись!
int main() {
Test** pF(void **a);
void *p = *static_cast<void* const*>(
static_cast<void const*>(
&static_cast<Test** (* const&)(void **a)>(&pF)));
}