Newsgroup: it.comp.lang.c
Titolo: Esiste un puntatore a void per le funzioni?

Se dichiaro ptr come puntatore a void:
--
  void *ptr;
--
posso assegnare un qualsiasi tipo di puntatore, senza errori né
warning:
--
  char c;
  int i;
  long l;
  ptr = &c;
  ptr = &i;
  ptr = &l;
--
Esiste qualcosa del genere per le funzioni? Mi serve dichiarare un
puntatore a funzione generica (indipendentemente dal valore di ritorno
e dal numero/tipo di argomenti) e assegnare ad esso l'indirizzo di
funzioni C anche diverse.
Qualcosa del tipo:
--
  void (*f)(void);
  int f1( int, char, void *);
  void f2( void );
  void f3( unsigned int, long, char *);
  f = f1;
  f = f2;
  f = f3;
--
E' possibile?

 --
A parte che potresti provare a farlo...
Comunque a funzionare funziona, solo che devi sapere cosa stai 
assegnando per poi fare il casting corretto del puntatore

  void (*f)(void);
Questo è un puntatore a funzione che non prende parametri (void) e non
restituisce nulla.
Per memorizzare il puntatore puoi usare semplicemente:
void *f;
Il linguaggio garantisce la validità del passaggio T * -> void * -> T *
Certo non puoi invocare direttamente la funzione con quel puntatore (ma
non potresti farlo neppure con un ipotetico puntatore a funzione
"generico").
Luca
-- 
La mia opinione puo` essere cambiata, ma non il fatto che ho ragione.

 "generico").
Forse mi sfugge qualcosa.
Non mi è molto chiaro cosa volevi aggiungere rispetto
l'uso di un puntatore del tipo:
void (*f)(void);
Un puntatori fatto in questo modo può fungere bene
da puntatore generico per funzioni.
Con le opportune conversioni per portarlo
al puntatore corretto. Ovviamente.
--
Giorgio Silvestri
DSP/Embedded/Real Time OS   Software Engineer

 Oggetti (+ tipi incompleti) e funzioni sono "parrocchie" diverse.
(solo per completezza)
Riguardo a questo fatto, farebbe pero' eccezione il puntatore nullo 
(NULL), di solito definito di tipo "void *"
(eg: #define NULL ((void *)0) )
    6.3.2.3 Pointers
    .......
    3  An integer constant expression with the value 0,
    or such an expression cast to type void *, is
    called a null pointer constant. [55]) If a null
    pointer constant is converted to a pointer type,
    the resulting pointer, called a null pointer,
    is guaranteed to compare unequal to a pointer to
    any object or function.
    4  Conversion of a null pointer to another pointer
    type yields a null pointer of that type.
    Any two null pointers shall compare equal.
    .......
    55) The macro NULL is defined in <stddef.h> (and
    other headers) as a null pointer constant; see 7.17.
Secondo quanto scritto sopra, parrebbe chiaro che un puntatore a 
funzione si possa comunque inizializzare (o anche confrontare) con il 
valore NULL (e quindi a (void *)0).
Cioe', gli esempi sotto li riterrei conformi:
    int (*pf)(int, ...) = NULL;
    pf = (void *)0;
    if(pf == NULL) {  /* ..... */ }
    if(pf == (void *)0) {  /* ..... */ }
Ciao e Buon Anno a tutti!
PS: scusate il testo scritto di fretta
-- 
Cybertoldo
Per rispondermi via email, sostituisci moc.liamg con 
gmail.com

 Riguardo a questo fatto, farebbe pero' eccezione il puntatore nullo
Infatti è un caso speciale.


 al puntatore corretto. Ovviamente.
Indendevo appunto che non puoi usarlo direttamente per invocare la
funzione (o meglio: puoi ma il risultato è undefined), devi comunque
tornare al tipo corretto.
Luca
-- 
Pare che gli uomini facciano l'amore di continuo e le donne solo
raramente. Ci dev'essere qualcuno che bara.

 al puntatore corretto. Ovviamente.
Scusate il ritardo... ma le feste son feste :)
Allora io definisco una mia struttura ed una funzione in questo modo:
--
  int sum( int a, int b );
  typedef struct {
    int type;
    void (*f)(void);
  } miotipo;
--
Tramite il campo type riesco a capire il tipo di funzione a cui punta
il campo f e quindi a fare
un cast corretto.
Ora definisco una mia variabile in questo modo:
--
  const miotipo s = { 1, sum };
--
Il compilatore mi dà warning che si risolve così:
--
  const miotipo s = { 1, (void(*)(void)) sum };
--
Non c'è altra soluzione per evitare il warning? Devo fare un lungo
elenco e mi scocciano un 
po' tutti questi cast.

 po' tutti questi cast.
Un giochino che mi piace fare con le macro, tanto per
parametrizzare e non scrivere sempre le stesse cose
più volte ... :
typedef struct {
        int type;
        void (*f)(void);
} miotipo;
static int sum(int x,int y)
{
        return x+y;
}
static int diff(int x,int y)
{
        return x-y;
}
static int neg(int x)
{
        return -x;
}
#define CT(T,FUN) {TYPE_ ## T, (void(*)(void))(FUN) },
enum {
    TYPE_i_ii = 1,      /* torna int e prende 2 int */
    TYPE_i_i              /* torna int e prende int */
};
static miotipo s[] = {
        CT(i_ii,sum)
        CT(i_ii,diff)
        CT(i_i,neg)
};


Giorgio Silvestri ha scritto:

...carina! :)
Ma se si spaventa, anche una semplice typedef puo' aiutare:
typedef void (*void_fp)(void);
typedef struct {
         int type;
         void_fp f;
} miotipo;
static int sum(int x,int y)
{
         return x+y;
}
miotipo s = { 1, (void_fp) sum };
Ciao
