Newsgroup: it.comp.lang.c
Titolo: ptr a funzioni: un dubbio (standard ?)

Con la seguente porzione di codice:
int mod(int a, int b)
{
    return a%b;
}
int (*f) (int, int);
dichiaro f come ptr a una funzione intera che vuole due
argomenti interi.
Perche' le notazioni
f = mod;    [1]
f = &mod;   [2]
hanno esattamente lo stesso effetto?
e l'uso di f, sia che io lo valorizzi con [1] che con [2],
puo' essere indifferentemente:
c = f(4,3);       [1]
c = (*f)(4,3);    [2]
qual'e' dele due notazioni e' piu' corretta?
cosa prevede lo standard (Laforgia, se ci sei dimmi la tua opinione...)?
e perche' posso mescolare le due notazioni, senza che
il compilatore mi segnali nessun warning (gnu con opzione -Wall)
e ottenere lo stesso risultato?
Secondo me la combinazione delle notazioni [2] dovrebbe
essere quella piu' corretta, dato che f e' un ptr: valorizzo
f con l'indirizzo dell'oggetto che mi interessa (una funzione,
in questo caso), e quando lo uso lo referenzio con *f, come
normalmente si fa con i ptr. Quanto meno a me viene piu' naturale
pensarla e capirla, anche se e' piu' compatta la notazione [1].
A me lascia molto perplesso il fatto di avere delle scritture
che a prima vista significano due cose diverse (f e *f, mod e &mod)
ma che in realta' sono la stessa cosa, tanto che le posso
mescolare senza problemi.
buon grazie a chiunque voglia aiutarmi a chiarire questo dubbio.
bepin

mescolare senza problemi.
Temo che non sia esattamente cosi'.
Non ricordo cosa dice lo standard a proposito, ma temo che i tipi di
mod e &mod non siano gli stessi.

 c = (*f)(4,3);    [2]
Quella corretta e la prima.
L'operatore chiamata a funzione ha un doppio effetto:
es:
void funzione(void) {}
int main(void) {
    funzione; // restituisce l'indirizzo di memoria del primo byte che
compone la funzione;
   *funzione; // restituuisce il primo byte della funzione;
    funzione(); // dereferenzia funzione, mette gli eventuali parametri
nello stack e ed esegue il corpo della funzione
}
Sui puntatori a funzioni valgono le stesse regole appena viste.
La sintassi da te presentata, ovvero (*f)(4,3), - ovviamente senza offesa -
è un pasticcio in quanto fa tutto meno che eseguire una chiamata a funzione.
NB: il nome di una funzione e il nome di un array non sono puntatori finché
non vengono utilizzati nelle espressioni. Anche se molti libri di testo
semplificano il discorso dicendo che lo sono, non è del tutto esatto.
Considerarli come puntatori può indurre a scrivere codici come:
void funzione(void) {}
int main(void) {
    ++funzione;
}
che peraltro sono situazioni passibili almeno di un warning da parte del
compilatore.
Ciao.

 è un pasticcio in quanto fa tutto meno che eseguire una chiamata a
funzione.
Errore mio di lettura, mi sono confuso con (*f). E' valida.
Ciao.

è un pasticcio in quanto fa tutto meno che eseguire una chiamata a
funzione.
Nessuna offesa, figurati, sto solo cercando di capire.
Non sono convintissimo che per i ptr a funzione valgano le stesse regole...
Il dubbio nasce dal fatto che:
se io scrivo
void f(void)
{
}
e poi uso
(*f)();
non solo fa di tutto, ma il compilatore pure mi da un
erroraccio che non ricordo, ma pertinente;
ma se io scrivo:
void f(void)
{
}
void (*pf)(void) = f;
riesco ad usare sia
pf();
che
(*pf)();
e ottengo lo stesso risultato, ovvero la seconda esegue
una chiamata di funzione.
E nota che compilo usando Gnu gcc con l'opzione -Wall,
e non ho neppure warning
rissumendo:
se f e' il nome di una funzione, sono d'accordo
che (*f)() sia un pasticcio
ma se f e' un ptr a funzione, secondo me
la notazione (*f)() e' legale e ha sicuramete lo stesso
effetto di f() (almeno con il compillatore Gnu).
ciao
bepin

azz... postato in contemporanea, non avevo letto il tuo post.
sorry
bepin

Quella corretta e la prima.
Anche la prima.

effetto di f() (almeno con il compillatore Gnu).
Si', e' cosi'.

Tratto dall'ANSI C Rationale:
3.3.2.2  Function calls
Pointers to functions may be used either as (*pf)() or as pf().  The
latter construct, not sanctioned in the Base Document, appears in some
present versions of C, is unambiguous, invalidates no old code, and
can be an important shorthand.  The shorthand is useful for packages
that present only one external name, which designates a structure full
of pointers to objects and functions: member functions can be called
as graphics.open(file) instead of (*graphics.open)(file).  
The treatment of function designators can lead to some curious, but
valid, syntactic forms.  Given the declarations: 
        int f(), (*pf)();
then all of the following expressions are valid function calls: 
        (&f)(); f(); (*f)(); (**f)(); (***f)();
        pf();   (*pf)(); (**pf)(); (***pf)();

 mescolare senza problemi.
E' un po' lo stesso discorso degli array che decadono in puntatori.
Anche i nomi delle funzioni possono decadere in puntatori a funzione.
EMG

 Probabilmente usi un compilatore C++.
No, č un compilatore C.
Ringrazio comunque per la nota e per il post seguente.
PS: hai lo standard sotto mano??? Se sě, potresti inviarmene una copia vie
e-mail??
Ciao.

 erroraccio che non ricordo, ma pertinente;>
Questo mi stupisce assai. Qualche volta utilizzo anch'io il gcc, anche se
preferisco qualche ambiente grafico, e non mi restituisce errore sul codice
da te presentato.
Ciao.

>

Hai ragione, ho sbagliato io. In effetti, il compilatore non da nessun
errore compilando il seguente programma:
void f(void)
{
}
int main(int argc, char *argv[])
{
 (*f)();
 return 0;
}
buon giorno a tutti
bepin