Content que ton problème soit résolu 
Je réponds quand même à tes deux autres questions, ça peut servir.
write(int fd, const void *buf, size_t count);
Permet d'écrire dans un file descriptor quelquonque, ça peut être un fichier, mais aussi la sortie standrard (fd=1), ou la sortie d'erreur (fd=2), voir un socket. Comme c'est un appel système, l'écriture se fait "réellement" à son appel, tandis que si le programme plante après un printf, il est possible que tes donnée n'aient pas été "flushées", et donc tu peux chercher longtemps un bug avant le printf alors qu'il se situe après :p .
- En C les paramètres se transmettent bien par copie ?
Je vais pas dire de bêtise à propos des struct vu que je suis pas sûr, mais les tableaux sont passés par pointeurs (en fait en c ce *sont* des pointeurs.
Sinon pour débuguer, tu compiles avec gcc -g, et tu lances gdb en lui passant en argument le nom de ton programme, et tu tapes "run tes_params", ton programme se lancera, et s'arrêtera en te donnant des informations sur le nom de la fonction dans laquelle tu te trouves, et te permet d'afficher des variables avec la commande "p nom_de_variable".
Il y a d'autres commandes plus évolués dans gdb, mais avec ça tu peux déjà t'économiser pas mal de temps.