2013-01-05 17 views
5

In un sacco di esempi che ho letto un semplice getListLength() funzione sarebbe simile a questa:puntatori come argomenti di funzioni C

int getListLength(struct node *head) 
{ 
    struct node *temp = head; 
    int iCount = 0; 

    while (temp) 
    { 
     ++iCount; 
     temp = temp->next; 
    } 

    return iCount; 
} 

Quello che mi colpisce come non necessari è la dichiarazione di un puntatore locale (in questo caso * temp) che copia il parametro passato. Se ricordo correttamente, i parametri passati ottengono le proprie copie. Quindi, non ci sarà bisogno di un puntatore locale che copia la * testa solo perché la * testa è una copia stessa, giusto? In altre parole, sarebbe corretto scartare il puntatore * temp e usare invece head ovunque?

risposta

4

Sì, è una copia, quindi sì, sarebbe corretto.

int getListLength(struct node* head) 
{ 
    int iCount = 0; 

    while (head) 
    { 
     ++iCount; 
     head = head->next; 
    } 
    return iCount; 
} 

Perché non lo si esegue a vedere di persona?

4

Mentre è vero che non è necessaria la copia locale poiché il puntatore viene passato per valore, è probabilmente lì per ragioni stilistiche. Alcuni lo considerano una cattiva forma per modificare gli argomenti passati (anche se lo trovo utile in alcuni scenari), ma forse, cosa ancora più importante, si perde parte dell'autodocumentazione nel codice; nello specifico, head non punta sempre più al vero capo dell'elenco collegato. Non è questo che confonde il tuo breve pezzo di codice, ma avere variabili con un nome errato può essere molto più confuso quando il codice è più lungo e più complesso.

+0

"quando il codice è più lungo e più complesso." - Potrei discutere con quello. Se una funzione è più lunga dell'OP pubblicato, e se è così complessa da svolgere più di una attività e occorre ricordare i nomi delle variabili, è probabile che tale funzione venga probabilmente rifatta. –

+0

Probabilmente è vero, ma il mondo reale raramente è perfetto come potrebbe piacerti. – jjlin

2

Spesso, la ragione per creare una copia locale di un puntatore passato è ridurre lo side-effects di una funzione (non modificando il parametro della funzione).

Se una funzione è solo utilizzando il puntatore per leggere (non scrivere), e ha nessun'altra interazione con il mondo esterno, la funzione potrebbe essere annotato come 'puro' in GCC e sarebbe aperto per alcune belle ottimizzazioni.

Esempio:

__attribute__((pure)) int getListLength(struct node *head) 
{ 
    struct node *temp = head; 
    int iCount = 0; 

    while (temp) 
    { 
     ++iCount; 
     temp = temp->next; 
    } 

    return iCount; 
} 

Se non si ha familiarità con ciò che gli effetti collaterali sono, provare a leggere i Side Effects e Functional Programming articoli di Wikipedia per avere maggiori informazioni su questo argomento.

Problemi correlati