Ricerca…


Osservazioni

In C, è comune utilizzare i valori di ritorno per indicare gli errori che si verificano; e per restituire i dati tramite l'uso dei puntatori passati. Questo può essere fatto per molteplici ragioni; incluso non dover allocare memoria sullo heap o utilizzare l'allocazione statica nel punto in cui viene chiamata la funzione.

Utilizzo dei parametri del puntatore per restituire più valori

Un modello comune in C, per imitare facilmente la restituzione di più valori da una funzione, è utilizzare i puntatori.

#include <stdio.h>

void Get( int* c , double* d )
{
    *c = 72; 
    *d = 175.0;
}

int main(void)
{
    int a = 0;
    double b = 0.0;

    Get( &a , &b );

    printf("a: %d, b: %f\n", a , b ); 

    return 0;
}

Passare da array a funzioni

int getListOfFriends(size_t size, int friend_indexes[]) {
  size_t i = 0;
  for (; i < size; i++) {
    friend_indexes[i] = i;
  }
}
C99 C11
/* Type "void" and VLAs ("int friend_indexes[static size]") require C99 at least. 
   In C11 VLAs are optional. */
void getListOfFriends(size_t size, int friend_indexes[static size]) {    
  size_t i = 0;
  for (; i < size; i++) {
    friend_indexes[i] = 1;
  }
}

Qui la static all'interno di [] del parametro function, richiede che la matrice di argomenti abbia almeno tanti elementi quanti sono specificati (es. Elementi di size ). Per essere in grado di utilizzare tale funzione, dobbiamo assicurarci che il parametro size venga prima del parametro array nell'elenco.

Usa getListOfFriends() questo modo:

#define LIST_SIZE (50)

int main(void) {
  size_t size_of_list = LIST_SIZE;
  int friends_indexes[size_of_list];

  getListOfFriends(size_of_list, friend_indexes); /* friend_indexes decays to a pointer to the
                                                     address of its 1st element: 
                                                                      &friend_indexes[0] */

  /* Here friend_indexes carries: {0, 1, 2, ..., 49}; */

  return 0;
}

Guarda anche

Passaggio di array multidimensionali a una funzione

I parametri sono passati per valore

In C, tutti i parametri di funzione vengono passati per valore, pertanto la modifica di ciò che viene passato nelle funzioni di chiamata non influisce sulle variabili locali delle funzioni del chiamante.

#include <stdio.h>

void modify(int v) {
    printf("modify 1: %d\n", v); /* 0 is printed */
    v = 42;
    printf("modify 2: %d\n", v); /* 42 is printed */
}

int main(void) {
    int v = 0;
    printf("main 1: %d\n", v); /* 0 is printed */
    modify(v);
    printf("main 2: %d\n", v); /* 0 is printed, not 42 */
    return 0;
}

È possibile utilizzare i puntatori per consentire alle funzioni callee di modificare le variabili locali delle funzioni del chiamante. Si noti che questo non è passato per riferimento, ma i valori del puntatore che puntano alle variabili locali vengono passati.

#include <stdio.h>

void modify(int* v) {
    printf("modify 1: %d\n", *v); /* 0 is printed */
    *v = 42;
    printf("modify 2: %d\n", *v); /* 42 is printed */
}

int main(void) {
    int v = 0;
    printf("main 1: %d\n", v); /* 0 is printed */
    modify(&v);
    printf("main 2: %d\n", v); /* 42 is printed */
    return 0;
}

Tuttavia, la restituzione dell'indirizzo di una variabile locale al callee comporta un comportamento indefinito. Vedi Dereferenziare un puntatore alla variabile oltre la sua durata .

Ordine di esecuzione del parametro funzione

L'ordine di esecuzione dei parametri non è definito nella programmazione C. Qui può essere eseguito da sinistra a destra o da destra a sinistra. L'ordine dipende dall'implementazione.

#include <stdio.h>

void function(int a, int b) 
{
    printf("%d %d\n", a, b);
}

int main(void)
{
    int a = 1;
    function(a++, ++a);
    return 0;
}

Esempio di funzione che restituisce una struct contenente valori con codici di errore

La maggior parte degli esempi di una funzione che restituisce un valore implica la fornitura di un puntatore come uno degli argomenti per consentire alla funzione di modificare il valore puntato a, simile al seguente. Il valore di ritorno effettivo della funzione è solitamente un tipo, ad esempio un int per indicare lo stato del risultato, indipendentemente dal fatto che abbia funzionato o meno.

int func (int *pIvalue)
{
    int iRetStatus = 0;             /* Default status is no change */

    if (*pIvalue > 10) {
        *pIvalue = *pIvalue * 45;   /* Modify the value pointed to */
        iRetStatus = 1;             /* indicate value was changed */
    }

    return iRetStatus;              /* Return an error code */
}

Tuttavia, è possibile utilizzare anche una struct come valore di ritorno che consente di restituire sia uno stato di errore insieme ad altri valori. Per esempio.

typedef struct {
    int    iStat;      /* Return status */
    int    iValue;     /* Return value */
}  RetValue;

RetValue func (int iValue)
{
    RetValue iRetStatus = {0, iValue};

    if (iValue > 10) {
        iRetStatus.iValue = iValue * 45;
        iRetStatus.iStat = 1;
    }

    return iRetStatus;
}

Questa funzione potrebbe quindi essere utilizzata come il seguente esempio.

int usingFunc (int iValue)
{
    RetValue iRet = func (iValue);

    if (iRet.iStat == 1) {
        /* do things with iRet.iValue, the returned value */
    }
    return 0;
}

O potrebbe essere usato come il seguente.

int usingFunc (int iValue)
{
    RetValue iRet;

    if ( (iRet = func (iValue)).iStat == 1 ) {
        /* do things with iRet.iValue, the returned value */
    }
    return 0;
}


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow