2014-11-15 2 views
6

ho trovato una funzione ricorsiva che mi ha lasciato un po 'sorpreso di questa funzione conta i numeri tutti negativi che compaiono in un array:Strano espressione nella istruzione return

int count_negative(int arr[], int n) 
{ 
    if (n > 0) 
    return (*arr < 0) + count_negative(++arr, n - 1); 
    return 0; 
} 

Qualcuno può spiegare questa linea:

return (*arr < 0) + count_negative(++arr, n-1); 

Grazie

+1

Questa è un'implementazione piuttosto scadente della ricorsione; non è idoneo per essere convertito in coda, quindi le prestazioni ne risentiranno rispetto a un'implementazione iterativa. – cdhowie

+3

Non questo '(* arr ...) + count_negative (++ arr, ...' provoca UB? – alk

+0

@cdhowie: GCC sembra proprio bene al TCO. – ninjalj

risposta

6

(*arr < 0) confronta il primo elemento dell'array con zero. Il risultato dell'espressione può essere 1 (il primo elemento è negativo) o 0 (il primo elemento è positivo o zero). Quindi, il numero di elementi negativi è la somma di questa espressione e il numero di elementi negativi nella coda dell'array.

3

*arr punti al primo elemento di arr array (o, più precisamente, la parte del arr che è stato passato alla funzione in questa particolare chiamata).

count_negative(++arr, n-1) è una chiamata ricorsiva ma a causa della ++arr, all'interno di questa chiamata contare il successivo elemento della matrice e n-1 argomento, togeher con le if (n > 0) garanzie che avremo contare soltanto elementi all'interno della matrice arr.

2

Il principio è che invece di tenere un indice sull'elemento da ispezionare, poiché arr è un puntatore e la modifica non cambierà i dati, si può invece usare arr come iteratore sui dati dell'array.

Quindi, *arr < 0 controlla se l'elemento appuntito corrente è negativo (sarà resa 1 caso affermativo, 0 se non), e ++arr incrementa il cursore al prossimo posto nella matrice, che viene quindi passato in modo ricorsivo controlla la resto dell'array.

Questa è un'idea molto conosciuto in linguaggi funzionali d'uso delle liste in cui si lavora spesso sul primo elemento della lista (la testa) e ricorsione sul restante della lista (la coda).

+2

Ora capisco ie (* arr <0) sarà 1 o 0 a seconda se si tratta di un numero negativo – cheroky

+0

Esatto. '1' e' true' sono lo stesso valore in C – didierc

+1

2 è anche vero ... ;-) – alk