Newsgroup: it.comp.lang.c
Titolo: Una funzione può restituire un array ?

Se ridefinisco il tipo 
typedef float Vettore[100];
posso scrivere una cosa del genere ?
Vettore somma_vettori(Vettore S, Vettore T, int n)
{
Vettore v;
....
v=S+T // pseudocodice
return (v)
}
a me da un errore di compilazione.
Grazie dei suggerimenti
Francesco

nome".
Non diciamo stupidate. In C, come in C++, T[] e T* sono due tipi
distinti. Solitamente T[] decade a puntatore al primo elemento (T*),
tranne nei tre famosi casi: T[] e` l'operando di sizeof, T[] e`
l'operando di & (address-of), T[] e` coinvolto nell'inizializzazione
tramite literal.
Luca
-- 
Home: 
http://kronoz.cjb.net
Se alla sera, dopo una strepitosa vittoria, guardandoti allo
specchio dovessi notare un secondo paio di palle, che il tuo 
cuore non si riempia d'orgoglio, perche` vuol dire che ti 
stanno inculando -- Saggio Cinese

 a me da un errore di compilazione.
Non e` lecito infatti. Potresti restituire un float*, ma in questo caso
la soluzione sarebbe scorretta sementicamente in quanto verrebbe
restituito un puntatore ad una variabile locale di tipo auto.
Puoi fare in modo che il caller ti passi anche l'array in cui inserire
il risultato:
void somma_vettori(Vettore S, Vettore T, Vettore ret, int n) {
        for(...)
                ret[i] = S[i] + T[i];
}
oppure puoi allocare dinamicamente l'array per il risultato:
float *somma_vettori(Vettore S, Vettore T, int n) {
        float *ret;
        /* array di n float */
        ret = malloc(n * sizeof(float));
        if (ret == NULL)
                errore("Out of memory");
        for(...)
                ret[i] = S[i] + T[i];
        return ret;
}
In quest'ultimo caso dovrai avere l'accortezza di liberare la memoria
con free() una volta che i dati non ti servono piu`.
Luca
-- 
Home: 
http://kronoz.cjb.net
"Chi parla in tono cortese, ma continua a prepararsi, potra` andare avanti;
 chi parla in tono bellicoso e avanza rapidamente dovra` ritirarsi" 
Sun Tzu -- L'arte della guerra

>nome".
In ogni caso non è il preprocessore che fa una cosa del genere...

 primo elemento del vettore stesso.
No.
int a[10];
int *b;
sono due tipi diversi. Il primo e` array-di-10-int, il secondo e`
puntatore-a-int. Puo` accadere che array-di-10-int *decada* a
puntatore-a-int, ma non sono la stessa cosa.
Luca
-- 
Home: 
http://kronoz.cjb.net
La mia opinione puo` essere cambiata, ma non il fatto che ho ragione.

 }
Ese invece creo una struttura in cui il primo membro è l'array ed il
secondo membro è la dimensione dell'array? Sarebbe fattibile? Potreste
darmi un esempio di codice?
Ringrazio tutti per le risposte date al mio quesito.
Francesco

 darmi un esempio di codice?
Non ho ben capito cosa tu voglia fare... forse una cosa come questa?
struct vettore {
        float data[123];
};
struct vettore somma_vettori(vettore a, vettore b) {
        struct vettore ret;
        /* nota che la dimensione si puo` ottenere con
         * sizeof(a.data) / sizeof(a.data[0])
         */
        for(...)
                ret.data[i] = a.data[i] + b.data[i];
}
Funzionare funziona, ma e` molto poco efficente visto che ci sono molte
copie di oggetti potenzialmente grossi. Quando scrivi:
foo = somma_vettori(a, b);
Ci sono ben 4 copie di dati: prima viene fatta una copia dei parametri
(/a/ e /b/), poi una copia di /ret/ in una struttura temporanea ed
infine la copia della struttura temporanea su /foo/.
Si potrebbero evitare le due copie di /a/ e /b/ passando un puntatore
alla struttura, ma rimarrebbero comunque 2 copie da fare...
Luca
-- 
Home: 
http://kronoz.cjb.net
#include <stdio.h> 
int main(void) {printf("\t\t\b\b\b\b\b\b");
printf("\t\t\b\b\b\b\b\b");return 0;}

 puntatore-a-int, ma non sono la stessa cosa.
Giustissimo. Però forse fgr si riferiva ai parametri delle funzioni 
dichiarati nella forma
     T arg []
Questa è a tutti gli effetti la dichiarazione di un puntatore, non 
di un array, ed è totalmente equivalente a
  T * arg
Infatti 'arg' può anche essere usato come L-value. Ad es:
  void func( int arg[] )
  {
         arg = NULL; 
  }
Tale assegnamento non sarebbe lecito se 'arg' fosse un array.
Max

 comunque 2 copie da fare...
In effetti non è che avessi fatto grande attenzione all'efficienza
dell'algoritmo. Ma per piccoli array non credo possa essere considerato un
problema. E poi, come suggerisci tu, si potrebbe sempre passare il
puntatore alla struttura degli argomenti, e magari restituire un puntatore
alla struttura.
Francesco

 alla struttura.
Non in quell'esempio. Se cambiassi la funzione cosi`:
struct vettore *somma_vettori(vettore *a, vettore *b) {
        struct vettore ret;
 
        ...
 
        return &ret;
}
Restituiresti un puntatore ad una variabile locale di tipo auto, che non
e` corretto: la variabile "scompare" all'uscita dalla funzione, avresti
un puntatore ad un area di memoria non valida o, peggio ancora, usata da
qualcos'altro.
Dovresti fare (e torniamo all'esempio che ho fatto prima):
struct vettore *somma_vettori(vettore *a, vettore *b) {
        struct vettore *ret;
        ret = malloc(sizeof(*ret))
        if (ret == NULL)
                errore();
        ...
        return ret;
}
Luca
-- 
Home: 
http://kronoz.cjb.net
Quando un uomo porta dei fiori a sua moglie senza motivo, 
un motivo c'e`.

 }
Ecco, qualcosa del genere, anche se un poco più complicato di quanto
pensassi. 
Ti ringrazio per l'estrema gentilezza
Francesco

 pensassi. 
Beh, i pattern sono due: il chiamante fornisce la struttura per
l'output, il chiamato alloca la struttura per l'output[1]. In questo
caso io userei il primo, fare restituire una struttura allocata con
malloc complica sempre il codice (devi tracciare l'uso di quel
puntatore, ricordarti la free(), verificare di non usarlo dopo la free,
ecc.); personalmente lo faccio solo quando la funzione serve da
costruttore per l'oggetto.
Questione di gusti comunque ;)
Luca
[1] Volendo c'e` la possibilita` di restituire un puntatore ad una
struttura statica. A me non piace, ma ci sono degli usi validi... IMMV.
-- 
Home: 
http://kronoz.cjb.net
"Ricorda sempre che sei unico, esattamente come tutti gli altri".

Kronos, vedo che ogni volta hai una signature diversa, cosa usi?
-- 
Devaraja (Xdevaraja87^gmail^c0mX)
Linux Registerd User #338167
http://counter.li.org

 Kronos, vedo che ogni volta hai una signature diversa, cosa usi?
Tin come client, un piccolo programma scritto in C per scegliere una
signature random da una directory.
Luca
-- 
Home: 
http://kronoz.cjb.net
Porc i' mond che cio' sott i piedi!
V. Catozzo