È legale assegnare di nuovo un puntatore alla funzione?


33

I puntatori alle funzioni non sono semplici puntatori di dati in quanto non possono essere memorizzati in un puntatore void *. Tuttavia, sembra che sia possibile memorizzare la copia di un puntatore a funzione nella memoria dinamica (in gcc e clang) come nel codice seguente. Un tale codice è legale secondo lo standard C ++ o forse si tratta di una sorta di estensione del compilatore?

Inoltre, il puntatore risultante al puntatore-funzione si comporta come un semplice puntatore di dati: posso memorizzarlo in void * e recuperarlo da void * tramite static_cast. Questo comportamento è garantito dalla norma?

int main()
{
  extern void fcn();
  void (*fcnPtr)() = &fcn;
  void (**ptrToFcnPtr)() = nullptr;

  //Make the copy of fcnPtr on the heap:
  ptrToFcnPtr = new decltype(fcnPtr)(fcnPtr);
  //Call the pointed-to function : 
  (**ptrToFcnPtr)();

  //Save the pointer in void* :
  void *ptr = ptrToFcnPtr;
  //retrieve the original ptr: 
  auto myPtr = static_cast< void(**)() > (ptr) ; 
  //free memory:
  delete ptrToFcnPtr ;

}

2
Si prega di non utilizzare i puntatori a funzioni non elaborate. Usa std::functioninvece.
Qualche programmatore amico

Non è necessario il newcast a void*. void* ptr = &fcnPtr;funziona altrettanto bene, poiché fcnPtrè un oggetto, non una funzione.
noce

5
@Someprogrammerdude std::functionè un contenitore cancellato dal tipo per l'archiviazione di una chiamata arbitraria, non proprio un sostituto per i puntatori a funzione ...
Michael Kenzel

7
(@Someprogrammerdude) Si prega di non utilizzare ciecamente / raccomandare std::function. È ottimo per la sua capacità di memorizzare funzioni "polimorfiche" (cioè qualsiasi cosa con la firma giusta, anche se contiene stato come nel caso di alcuni lambda), ma ciò aggiunge anche un sovraccarico che potrebbe non essere necessario. Un puntatore a una funzione è POD. A std::functionnon lo è.
Matteo,

2
@Matthew Ad essere sinceri, Adrian sta chiedendo di allocare dinamicamente il puntatore alla funzione e di indicarlo con una cancellazione del tipo void*, quindi nel contesto di questa domanda std::functionsembra essere esattamente quello che stavano cercando. Sono d'accordo sul fatto che il licenziamento generale da parte di SPD dei puntatori a funzioni non sia corretto.
Eerorika,

Risposte:


27

Mentre i puntatori a funzione non sono puntatori a oggetti, "puntatore a una funzione di un certo tipo" è ancora un tipo di oggetto [basic.types] / 8 . Pertanto, i puntatori a funzione sono essi stessi oggetti, proprio ciò che indicano non lo è.

Quindi, puoi sicuramente creare un oggetto di tipo puntatore a funzione tramite una nuova espressione ...


9

poiché (puntatori a funzione) non possono essere memorizzati in un puntatore void *.

In realtà, la memorizzazione di un puntatore a funzione come void*è supportata in modo condizionale. Ciò significa che può o non può essere memorizzato a seconda dell'implementazione della lingua. Se l'implementazione della lingua supporta il caricamento dinamico, void*probabilmente è supportata la conversione del puntatore a funzione . GCC, Clang e MSVC supportano tutti questo:

reinterpret_cast<void*>(&function);

È legale assegnare di nuovo un puntatore alla funzione?

Sicuro. Tutti i puntatori, inclusi i puntatori a funzioni, sono oggetti e tutti gli oggetti possono essere allocati in modo dinamico.

Inoltre, il puntatore risultante al puntatore-funzione si comporta come un semplice puntatore di dati

Il puntatore a funzione è un oggetto. Puntatore a un puntatore a funzione non solo "si comporta come", ma è un puntatore a un oggetto.

Posso archiviarlo nel vuoto * e recuperarlo dal vuoto * tramite static_cast. Questo comportamento è garantito dalla norma?

La conversione tra puntatore a vuoto e puntatore a oggetto è consentita, sì. E la conversione di andata e ritorno è garantita per fornire il puntatore originale.


Grazie. Ma poi per convertire il pointer-funzione in void * (o viceversa) devo usare reinterpret_cast, giusto?
Adrian,

1
@Adrian Sì. Ho aggiunto un esempio.
eerorika,

Se qualcuno vuole un'eccezione probabilmente: dos media memoria modello + overlay. I puntatori a funzione sono più grandi dei puntatori a dati nel modello medio e gli overlay possono essere usati per ottenere plugin se ci provi abbastanza.
Joshua,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.