2013-06-12 14 views
11

In C++ (GNU GCC g ++), il mio codice sta "chiamando" una funzione senza(). La funzione non funziona, ma compila ok.g ++ "chiama" una funzione senza parentesi (non f() ma f;). Perché restituisce sempre 1?

Più sorprendentemente, il codice restituisce sempre 1 ...

C'è una spiegazione?

mi aspettavo il nome della funzione di essere solo un puntatore normale, ma sembra che sia un po 'diverso ...

ho ricevuto tutti 1 solo per caso?

#include <iostream> 
using namespace std; 

void pr() 
{ 
    cout << "sth"; 
} 

int main() 
{ 

pr; 
cout << pr; // output: 1 
cout << *pr; // output: 1 
cout << &pr; // output: 1 

} 
+11

Cast implicito a bool di un indirizzo di funzione. –

+1

Questo post può essere utile: http://stackoverflow.com/questions/2064692/how-to-print-function-pointers-with-cout – taocp

+1

Conversione ** implicita ** al bool di un indirizzo di funzione. Non esiste una cosa come nel cast implicito. –

risposta

13

Non sta effettivamente chiamando pr nel codice, si sta passando il puntatore a funzione a cout. pr viene convertito in un bool quando viene passato a cout. Se si inserisce cout << boolalpha in anticipo, verrà emesso true anziché 1.

EDIT:
Con C++ 11 si può scrivere il seguente overload:

template <class RType, class ... ArgTypes> 
    std::ostream & operator<<(std::ostream & s, RType(*func)(ArgTypes...)) 
    { 
     return s << "(func_ptr=" << (void*)func << ")(num_args=" 
       << sizeof...(ArgTypes) << ")"; 
    } 

il che significa che la chiamata cout << pr stamperà (func_ptr=<address of pr>)(num_args=0). La funzione stessa può fare tutto ciò che vuoi ovviamente, questo è solo per dimostrare che con i modelli variadici di C++ 11, puoi abbinare i puntatori a funzioni di arbitrarietà arbitraria. Questo ancora non funzionerà per funzioni sovraccaricate e modelli di funzioni senza specificare quale sovraccarico si desidera (di solito tramite un cast).

+0

E questo è un errore negli iostreams C++ tipizzati. O meglio, nelle conversioni implicite di C++. – rubenvb

+0

@rubenvb Controlla la modifica, con C++ 11 c'è una cura per questo ora. – SirGuy

+0

@rubenvb bene, una cura per questa particolare trappola, non altri ... – SirGuy

4

Il nome di una funzione, se utilizzato senza parentesi, può essere inoltrato implicitamente a un puntatore di funzione. In effetti, quando si denomina o si fa riferimento a esso, non rimane altro che un puntatore di funzione o un puntatore a un puntatore di funzione, ecc. Questi puntatori di funzione, quando stampati, vengono convertiti implicitamente in bool, motivo per cui vengono semplicemente visualizzati 1. Se si desidera generare l'indirizzo di memoria effettivo della funzione, trasmetterlo a un puntatore del vuoto:

cout<<(void*)pr; 
+0

Più in generale, nella maggior parte dei contesti, un'espressione di tipo di funzione (incluso un nome di funzione) viene implicitamente convertita in un puntatore alla funzione. Le eccezioni sono quando si tratta dell'argomento 'sizeof' (che è illegale) o unary' &' (che fornisce l'indirizzo della funzione). Questo si applica anche quando il nome della funzione è seguito da parentesi; una chiamata di funzione richiede un puntatore a funzione come primo operando. –

+1

BTW, lanciare un puntatore a 'void *' è probabile che funzioni sulla maggior parte dei sistemi, ma non credo che il comportamento sia definito. (Ad esempio, la conversione potrebbe perdere informazioni se i puntatori di funzione sono più grandi di "void *".) –

+0

È mal formato; un'estensione del compilatore sarebbe necessaria per il funzionamento di questo codice. (E il codice dovrebbe emettere una diagnostica). In teoria l'estensione del compilatore dovrebbe documentare il suo comportamento. –

Problemi correlati