2012-11-20 2 views
7

Ho provato entrambi - C e C++ ed entrambi funzionano correttamente.Chiamare una funzione tramite un puntatore a funzione - dereferenziare il puntatore o no? Qual è la differenza?

Sono un po 'nuova per puntatori a funzione ed ecco un semplice codice, che mi ha sorpreso:

#include <assert.h> 
void sort(int* arr, const int N); 

int main() 
{ 
    int arr1[] = { 1, 5, 2, 6, 2 }; 
    int arr2[] = { 1, 5, 2, 6, 2 }; 

    void (*sort_ptr)(int*, const int) = sort; 

    sort_ptr(arr1, 5); 
    (*sort_ptr)(arr2, 5); 

    assert(arr1[0] == 1 && arr1[1] == 2 && arr1[2] == 2 && 
      arr1[3] == 5 && arr1[4] == 6); 
    assert(arr2[0] == 1 && arr2[1] == 2 && arr2[2] == 2 && 
      arr2[3] == 5 && arr2[4] == 6); 

    return 0; 
} 

void sort(int* arr, const int N) 
{ 
    // sorting the array, it's not relevant to the question 
} 

Quindi, qual è la differenza tra

sort_ptr(arr1, 5); 

e

(*sort_ptr)(arr2, 5); 

Entrambi sembrano funzionare (nessun errore, nessun avvertimento, array ordinati) e sono un po 'confuso. Qual è quello corretto o entrambi sono corretti?

risposta

15
sort_ptr(arr1, 5); 

e

(*sort_ptr)(arr2, 5); 

Entrambi sono corrette. In realtà, si può mettere il maggior numero di asterischi che si desidera e sono tutti corretti:

(*****sort_ptr)(arr2, 5); 

Il nome della funzione decade in un puntatore a una funzione. Quindi, il dereferenziamento produce ripetutamente lo stesso puntatore.

+0

perché ***** quanti ne vogliono, puoi spiegare? – Omkant

+0

Wow, è davvero strano per me. Perché la lingua lo permetterebbe? OK, sto bene usando uno '*' - potrebbe essere una sorta di dereferenziazione esplicita/implicita (come ha detto @Als nella sua risposta), ma perché permettere così tanti '*'? –

+5

Poiché formalmente, per chiamare una funzione, è necessario un puntatore a una funzione e una funzione viene convertita in modo implicito in un puntatore a una funzione. Ogni volta che aggiungi un '*, il risultato è una funzione, che converte in un puntatore alla funzione, che consente un ulteriore' * '. –

2

Per quanto riguarda il compilatore, sort_ptr e (*sort_ptr) sono identici. Se sort_ptr è davvero un puntatore, tuttavia, il dereferenziamento esplicito rende le cose molto più chiare per il lettore. In generale; c'è un caso in cui è utile il fatto che è possibile chiamare una funzione direttamente su un puntatore alla funzione: nei template, dove fa un puntatore per funzionare un oggetto funzionale, che si comporta esattamente come una classe con un operator()().