Newsgroup: it.comp.lang.c
Titolo: risultato di una funzione (non void) è necessariamente uno scalare?

Ciao.
In C il risultato di una funzione (se non è void) è necessariamente
uno scalare (quindi per esempio avente tipo int oppure float oppure
double) oppure può essere anche un vettore, per esempio di due
elementi?
Esempio: se funz è una funzione che ha come argomenti due qualsivoglia
fissate variabili locali, allora, supposto che funz restituisca un
risultato al chiamante, il risultato può essere un vettore?
Grazie in anticipo


Ovviamente si possono restituire puntatori, quindi sì:
int* f(void)
{
    int[2] v;
    v = calloc(sizeof(*v), 2);
    v[0] = 42;
    v[1] = 7;
    return v;
}

risultato al chiamante, il risultato può essere un vettore?
No.
Puoi però restituire un puntatore a una zona di memoria valida
(allocata nella funzione o preesistente), quindi sostanzialmente fai
la stessa cosa.

 elementi?
Purtroppo non e' possibile, pero' in C e' possibile restituire dei tipi 
struct quindi basta creare un tipo struct che contenga l'array che ti serve:
/* codice non compilato */
typedef struct {
   int a[2];
} risultato;
risultato f( int a, int b )
{
risultato R;
   R.a[0] = a;
   R.a[1] = b;
   return R;
}
ciao
Giacomo

    v = calloc(sizeof(*v), 2);
Questo codice è sbagliato. Avrebbe senso solo se v fosse un puntatore
a intero. E comunque attenzione a non fuorviare chi legge il codice:
"v" per cosa starebbe? per vettore? meglio usare "p" di puntatore,
perché vettori e puntatori sono cose profondamente diverse in C.
La risposta corretta alla domanda dell'OP è no, non sì. In C non si
possono restituire vettori, ma si può restituire un puntatore a una
zona di memoria allocata (o esplicitamente mediante allocazione
dinamica, o staticamente dal sistema).



quindi una funzione può restituire un puntatore a una zona di memoria
occupata da un vettore con un numero di elementi strettamente maggiore
di 1 per esempio?
grazie.

di 1 per esempio?
Certo, però devi stare attento al fatto che, all'uscita della
funzione, il contenuto del vettore (puntatore dal puntatore
restituito) sia ancora valido. Per intenderci, se scrivi:
int* myFunc() {
   int v[2];
   // ...
   return v;
}
Fai qualcosa di semanticamente valido, ma ERRATO nei fatti, perché il
contenuto di v è allocato sullo stack e all'uscita della funzione la
zona di memoria dello stack in cui i due interi sono allocati non è
più valida.
p.s.: un'alternativa che implica una restituzione per copia (e non per
riferimento come nel caso dei puntatori) è quella segnalata da
Giacomo, ovvero l'uso delle struct.

 dinamica, o staticamente dal sistema).
Beh, il vettore è un array bidimensionale, restituendo il puntatore
non fai altro che restituire il vettore, non capisco... Non c'è altro
modo per definire un vettore nello standard C (a meno di non usare una
struttura, ma comunque la cosa migliore è sempre restituire il
puntatore alla suddetta).
s.

>di 1 per esempio?
...e comunque il discorso vale anche per vettori contenenti 1 solo
elemento...

modo per definire un vettore nello standard C
Per definire un vettore nello standard C c'è un solo modo:
T vettore[dimensione];
con T qualsiasi tipo valido e dimensione un size_t > 0.
Quello a cui sto ribattendo è che se qualcuno chiede se una funzione
può restituire un vettore, la risposta è no. Poi si può valutare se
esistono strade alternative, come appunto l'uso di una struct che
racchiuda il vettore e che viene restituita quindi per copia oppure di
un puntatore che restituisce il contenuto del vettore per riferimento.

> modo per definire un vettore nello standard C
Scusa l'gnoranza potresti spiegarmi l'ultima parentetica ossia:
...(e non accade proprio sempre).
grazie bruce

...(e non accade proprio sempre).
I casi in cui il nome di un array non decade in puntatore al primo
elemento sono 3: 
caso 1: quando è argomento di & (address-of). Nel caso seguente:
int a[4];
scrivere &a significa ottenere un puntatore il cui tipo è "puntatore
ad array di 4 interi" e non "puntatore a puntatore a intero". Cioè, il
nome dell'array non decade a puntatore. Questo significa che qualsiasi
operazione aritmetica su quel &a, assume come spiazzamento
4*sizeof(int):
    int a[4];
    printf("a           = %p\n", a);
    printf("&a + 3      = %p\n", &a+3);
    printf("a + 3       = %p\n", a+3);
    printf("sizeof(int) = %d\n", sizeof(int));
    printf("(&a+3) - a  = %d\n", (size_t)(&a+3) - (size_t)a);
    printf("(a+3) - a   = %d\n", (size_t)(a+3) - (size_t)a);
output (sulla mia macchina):
    a           = 0022FF60
    &a + 3      = 0022FF90
    a + 3       = 0022FF6C
    sizeof(int) = 4
    sizeof a    = 16
    (&a+3) - a  = 48
    (a+3) - a   = 12
caso 2) quando è argomento di sizeof: il nome dell'array rappresenta
l'intero blocco di dati e non il singolo puntatore al primo elemento:
    int a[4];
    printf("sizeof a = %d\n", sizeof a);
    printf("sizeof (int*) = %d\n", sizeof (int*));
output (sulla mia macchina):
    sizeof a = 16
    sizeof (int*) = 4
caso 3) quando si sta inizializzando un array di caratteri mediante
string literal:
char a[] = "andrea";
Non si sta assegnando ad a il puntatore "andrea", ma l'espressione è
identica a:
char a[] = {'a','n','d','r','e','a','\0'};