Differenza tra il passaggio per valori / indirizzo e la restituzione di valori tramite le funzioni?

2

Secondo un libro che ho letto puoi passare variabili da una funzione all'altra passando per valore / indirizzo. Quando passi per indirizzo, non conserverà più la variabile se è stata modificata in una funzione e restituita alla funzione originale (es: main() ). Il capitolo successivo, il libro recensisce "valori di ritorno". In questo capitolo spiega l'uso di return(variable); ma non spiega uno scopo chiaro. return(variable); è utilizzato quando più variabili vengono passate a una determinata funzione per restituirne solo una? O ci sono altri usi? In altre parole, qual è la differenza tra return; e return(variable); ?

Passando per indirizzo, esatto esempio di libro senza return(num); :

#include <stdio.h>
main()
{
    int i;
    i = 4
    printf("Before: %d.\n", i);
    half(&i);
    printf("After: &d.\n", i);
    return (0);
}

half (int *i)
{
    *i = *i / 2;
    printf("During: %d.\n", *i);
    return;
}

Valori di ritorno, esatto esempio di libro con return(num); :

#include <stdio.h>
float gradeAve(float test1, float test2, float test3);

main()
{
    float grade1, grade2, grade3;
    float average;

    printf("What was the grade on the first test? ");
    scanf(" %f", &grade1);

    printf("What was the grade on the second test? ");
    scanf(" %f", &grade2);

    printf("What was the grade on the third test? ");
    scanf(" %f", &grade3);

    average = gradeAve(grade1, grade2, grade3);
    printf("\nWith those three test scores, the average is %.2f", average);

    return 0;
}

float gradeAve(float test1, float test2, float test3)
{
    float localAverage;
    localAverage = (test1+test2+test3)/3;
    return (localAverage); 
}

In che modo entrambi questi valori possono tornare alla funzione originale con o senza return(num); ?

    
posta Samuel F 14.05.2016 - 19:57
fonte

3 risposte

1

How can both of these return values to original function

Non lo fanno; il tuo libro è mal scritto.

  • Nel secondo caso:

    average = gradeAve(grade1, grade2, grade3);
    

    gradeAve restituisce - letteralmente con un'istruzione return - il suo risultato. Qui i parametri della funzione ( grade1..3 ) sono solo input e l'intera chiamata ha l'aspetto di un'espressione matematica.

  • Nel primo caso:

    half(&i);
    

    non viene restituito nulla . La variabile locale del chiamante, i , è mutata dalla funzione half , in modo che successivamente il suo valore sia diverso. Questo è chiamato out-parameter , il che significa che uno dei parametri della funzione viene utilizzato per l'output dalla funzione, anziché l'input alla funzione come avviene di solito.

    Questo stile di solito non è preferito perché è meno chiaro: non c'è nulla da dirmi quando leggo il codice chiamante che i è cambiato dalla chiamata finché non leggo anche l'implementazione di half .

    L'eccezione principale è quando il parametro out è di grandi dimensioni (quindi sarebbe costoso copiare per valore in un'istruzione return), oppure è un oggetto con qualche tipo di identità piuttosto che un semplice valore.

Una fonte di confusione (a parte la scarsa formulazione del libro) è che return fa due cose:

  1. passaggio di un risultato da una funzione al chiamante
  2. passaggio del controllo da una funzione al chiamante

Quindi ad esempio:

void mutate(int *i) {
  if (*i < 0) {
    return; /* just quit the function early */
  }
  (*i) = mutate_nonnegative(*i);
  /* return is implied here */
}

utilizza solo il significato # 2, mentre

int mutate_nonnegative(int i) {
  if (i % 2) {
    return 3 * i; /* triple odd numbers */
  } else {
    return 2 * i; /* double even numbers */
  }
}

usa sia il # 1 che il # 2 (esce dalla funzione e restituisce al chiamante in punti diversi, passando al chiamante un valore diverso per ciascuno).

    
risposta data 16.05.2016 - 19:57
fonte
1

Sono ancora molto confuso da questa domanda, ma potrebbe anche provare ...

Nella tua funzione half , l'istruzione return; non fa nulla di utile. Se la lasciassi fuori, la funzione si comporterebbe esattamente allo stesso modo. Allo stesso modo, anche le parentesi in return (localAverage); non fanno nulla e sono meglio tralasciate.

Normalmente return; è utile solo quando vuoi tornare dalla funzione "early", senza aspettare di colpire la parentesi graffa di chiusura. Come esempio banale:

saferHalf (int *i)
{
    if(i == NULL) {
        return;
    }
    *i = *i / 2;
    printf("During: %d.\n", *i);
}

How can both of these return values to original function with or without return(num);?

In generale, ci sono solo due modi per "restituire un valore" da una funzione. Innanzitutto, restituisci un valore, che significa utilizzare return value; . Secondo, si passa alla funzione un "parametro di output", cioè un puntatore a una variabile che la funzione dovrebbe modificare usando quel puntatore.

Non sono sicuro che tu fossi confuso su questo punto, ma il passaggio o il ritorno per valore o indirizzo non ha nulla a che fare con return; vs return value; o qualcosa del genere. A rigor di termini, C passa sempre per valore e restituisce per valore. I valori che si passano e ritornano possono essere dei puntatori e si può chiamare "pass / return by pointer / address" se lo si desidera, ma la semantica di passing e return è sempre la stessa o meno i valori che vengono passati e restituiti capita di essere puntatori.

    
risposta data 14.05.2016 - 23:22
fonte
0

È possibile utilizzare entrambi i metodi per restituire i valori al chiamante. Comunque in generale userò il seguente.

Salva il "valore di ritorno" per il risultato logico di un'operazione. Ad esempio, questo ha funzionato, c'è stato un errore, ecc. Se il tuo metodo vuole restituire un valore calcolato, invia il contenitore per quei dati nella richiesta e raccogli il risultato da lì.

Tuttavia, questa regola è fatta per essere infranta, quindi se vuoi solo restituire il risultato di una semplice aggiunta usa il valore di ritorno principale, piuttosto che dover passare la risposta contenuta nei parametri originali.

    
risposta data 16.05.2016 - 19:13
fonte

Leggi altre domande sui tag