Newsgroup: it.comp.lang.c
Titolo: Passare una struttura inizializzata ad una funzione

---
typedef struct {
  int x, y;
} Point;
void
foo(Point p)
{
  printf("x=%d y=%d\n", p.x, p.y);
}
void
bar(void)
{
  foo({1, 1});
}
---
Si può fare qualcosa del genere? Così come l'ho scritta non mi viene
accettata dal compilatore, magari esiste qualche altra sintassi... ho
paura che esista solo per il C99.


Questo codice non viene accettato dal compilatore perchè manca il
"cast" al tipo dell'oggetto in questione. Il compilatore gcc segnala
questa mancanza come errore in quanto conosce già questa sintassi, in
pratica si tratta di un "compound literal" [parlo di (Point){1,1}].
Con gcc è possibile utilizzare i "compound literals", anche senza
specificare la conformità al C99, perchè sono utilizzabili come
estensione. E' una funzionalità extra e niente più. Nel tuo codice
dicevamo che manca il "cast":
#include <stdio.h>
typedef struct {
     int x, y;
} Point;
void foo(Point p) {
     printf("x = %d, y = %d\n", p.x, p.y);
}
void bar(void) {
     foo((Point){1, 1});
}
int main(void) {
     bar();
     return 0;
}
------------
$ gcc main.c
$ ./a.out
x = 1, y = 1
------------
Questo codice viene compilato senza errori. Tuttavia:
-----------------------------------------------------
$ gcc -pedantic main.c
main.c: In function ‘bar’:
main.c:12: warning: ISO C90 forbids compound literals
$ ./a.out
x = 1, y = 1
-----------------------------------------------------
viene compilato lo stesso, ma il compilatore suggerisce che non è una
sintassi prevista dallo Standard C90. Invece:
-------------------------------
$ gcc -std=c99 -pedantic main.c
$ ./a.out
x = 1, y = 1
-------------------------------
Un piccolo appunto che voglio fare è sull'utilità di passare un'intera
struttura ad una funzione. Qui naturalmente ha poco senso soffermarsi,
perchè la struttura è di due soli interi. Ma naturalmente è molto
facile che le strutture siano composte da più membri ed è infatti per
questo motivo che generalmente si passa il puntatore a una struttura.
In questo caso il tuo codice andrebbe modificato in questo modo:
#include <stdio.h>
typedef struct {
     int x, y;
} Point;
void foo(Point *p) {
     printf("x = %d, y = %d\n", p->x, p->y);
}
void bar(void) {
     foo(&(Point){1, 1});
}
int main(void) {
     bar();
     return 0;
}
Gli output del compilatore sono identici.
-- 
Non puoi insegnare qualcosa ad un uomo. You cannot teach a man anything.
Lo puoi solo aiutare   --  Galileo  Galilei  --   You can only help him
a scoprirla dentro di sé.                        discover it in himself.
Vincenzo Mercuri

 questo motivo che generalmente si passa il puntatore a una struttura.
Questo per evitare di copiare sullo stack tutti i dati della struttura 
(che potrebbero essere tanti)?
In effetti hai ragione e spesso mi trovo a dover scegliere se passare 
puntatori a strutture oppure tutti i dati singolarmente come singoli 
argomenti. Anzi, spesso la necessitï¿½ di diminuire il numero degli 
argomenti delle funzioni mi porta a definire una struttura che li 
comprenda, il cui puntatore verrï¿½ passato come unico argomento.
Altre volte, poi, per lo stesso motivo, sono tentato di rendere globali 
alcune variabili (cosï¿½ da non doverle passare nï¿½ come singoli argomenti, 
nï¿½ come membri di una struttura). A livello di efficienza mi sembra 
l'approccio migliore (nessuna operazione sullo stack, solo la call), ma 
mi sembra una brutta pratica (anche se lavoro sull'embedded dove 
l'efficienza ï¿½ decisamente importante).

 l'efficienza è decisamente importante).
Minimizza i dati globali. Disegna il comportamento del tuo programma 
prima di mettere le mani sulla tastiera. Un buon progetto che faccia a
meno di variabili globali è un buon candidato ad essere un programma
robusto e con pochi bug.
