Se connecter avec
S'enregistrer | Connectez-vous

[C] Passer un tableau de structure complet dans une fonction

Dernière réponse : dans Programmation

Voilà, ça semble peut-être stupide comme question pour certain mais ... pour moi ça ne l'est pas :p 

Donc j'ai un tableau de structure qui ressemble à ça :

  1. struct Sentence {
  2. char text[255];
  3. int text_lenght;
  4. };
  5. struct Sentence* Paragraph = (struct Sentence *) malloc(10*sizeof(struct Sentence));


Je l'ai déclaré en dehors de toute fonction, juste en dessous des include.
Je voudrais pouvoir remplir et consulter ce tableau à partir de n'importe quel endroit, je suppose que c'est faisable mais après avoir testé un paquet de possibilités je commence à douter :( 

Pour être sûr d'être clair disons que je veux faire ça :
  1. int aff() {
  2. printf("%s", Paragraph[0].text);
  3. return 0;
  4. }

(En supposant que le tableau est rempli auparavant)

Merci d'avance pour vos precieux conseils :) 

PS : Je précise que c'est en C pas en C++
Lassé par la pub ? Créez un compte

Si tu la mis en global (juste en dessous des includes cela ne devrait pas poser de probleme.


  1. #include ...
  2.  
  3. struct Sentence
  4. {
  5. char text[255];
  6. int text_lenght;
  7. };
  8. struct Sentence* Paragraph;
  9.  
  10. main(à
  11. {
  12. Paragraph= (struct Sentence *) malloc(10*sizeof(struct Sentence));
  13. strcpy(Paragraph.text,"hehe");
  14. }
  15.  
  16. int aff() {
  17. printf("%s", Paragraph->text);
  18. return 0;
  19. }

Hum effectivement là ça fonctionne.
C'est peut-être dû au fait que je mettais cette ligne complète en dehors du main() :
  1. struct Sentence* Paragraph = (struct Sentence *) malloc(10*sizeof(struct Sentence));


Alors que toi tu la sépares en 2 et mets une partie dans le main().

Quoi qu'il en soit je te remercie bien !
Je vais essayer de continuer comme un grand :) 

KangOl a écritles variables globales spa bieng :o 


Ouais mais c'est pratique :lol: 
Nan je sais beaucoup vont dire, ouais il code comme un porc (si si j'vous entends d'ici) mais je suis encore semi-débutant donc l'optimisation ça arrivera seulement une fois que tout marchera correctement :) 

Là je suis content ça marche à peu près comme je le désire mais je fais une réallocation dans une de mes fonctions (lorsque l'utilisateur ajoute une nouvelle ligne, hop je fais une reallocation)

  1. realloc(Paragraph, nb_line*sizeof(struct Sentence));

(ou "nb_line" est incrémenté à chaque fois)

mais ça n'a pas l'air d'avoir d'effet (segmentation fault :sarcastic:  )

KangOl a écritc'est malin de realloc, tu effaces les données deja ecrites :o 

tu connais les listes chainées ??


T'es sûr le coup du realloc, moi mon man me dit ça :
"realloc() changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged to the minimum of the old and new sizes; newly allocated memory will be uninitialized."

Les listes chaînées, oui j'ai vu passer ça quelque part, c'est pourri à ce point la mon système ? (pourtant ça commencait à marcher)

nan, il est très bien ton code. Fait toi, juste une structure "haut dessus" pour garder aux chaud la taille réellle de ton tableau. Souvent les codeurs utilisent la liste chainé car il ne connaissent rien d'autre. C'est un des conteneurs le plus pourris qui soit (lent, gourmand en mémoire,...).

Vous battez pas :) 
J'ai conservé mon système de structure par manque de temps, mais j'essayerai tout de même avec les listes chaînées histoire de pas mourir idiot ;) 
Par contre après savoir lequel est le mieux là je vous laisse entre vous ...

Pour accéder à un élement de la liste tu dois la parcourir en entier vitesse donc proportionnel en nombre d'element donc en O(n).

Pour ajouter, un élement tu fais un malloc, c'est en O(1) mais un malloc est une opération système couteuse en temps.
Le free est hyper long car récursif.

Pour chaque élement, tu alloues un pointeur de plus. Donc 4 octets sont utilisés juste pour le plaisir. La mémoire n'est pas forcément contigue ce qui est mauvais pour la localité d'acces (et donc pour le cache). Mais c'est moins vrai si chaque élement est "gros" (en gros de l'ordre de grandeur d'une ligne de cache).

Si on utilise un tableau, l'acces est direct en o(1) et très peu couteux, c'est juste un calcul d'offset. Si on veut agrandir le tableau il faut faire un realloc qui couteux mais rien n'empèche d'allouer la mémoire par paquet de 10 élements. Donc, l'allocation coute 1 fois du 10.

free n'a besoin d'être appellé qu'une fois.

Ensuite, dans la manipulation des données, on manipule des indices et non plus des pointeurs. C'est beaucoup moins source d'erreur et cela génère du code plus rapide.

D'une manière général, si on peut éviter les pointeurs, on évite.

Le must étant d'utiliser les library de contener toute fait à l'image de la stl du c++. La plus reconnu est la glib.

Donc, la plus part du temps, il vaut mieux utiliser la glib.

cyrano a écrit
...
Ensuite, dans la manipulation des données, on manipule des indices et non plus des pointeurs. C'est beaucoup moins source d'erreur et cela génère du code plus rapide.

D'une manière général, si on peut éviter les pointeurs, on évite.

Le must étant d'utiliser les library de contener toute fait à l'image de la stl du c++. La plus reconnu est la glib.

Donc, la plus part du temps, il vaut mieux utiliser la glib.


Le compilateur ne modifie pas ton tab par *(tab+i) ? Mon prof m'avait que ceci

cyrano a écrit
Le must étant d'utiliser les library de contener toute fait à l'image de la stl du c++. La plus reconnu est la glib.

Donc, la plus part du temps, il vaut mieux utiliser la glib.

a ton avis, la glib, elle fait quoi ? des new et des delete...
donc je sais pas si c'est plus rapide qu'avec des tableaux...

ffomnislash a écritLe compilateur ne modifie pas ton tab par *(tab+i) ? Mon prof m'avait que ceci


Effectivement, j'ai appris cette notion hier même et je peux le confirmer. Cependant c'est plus comme ceci :
  1. int tab[100];
  2.  
  3. tab[i] est remplacé par *(tab + i*sizeof(int))


Où le type de données du tableau peux changer et le compilateur prends le sizeof() du type de données du tableau.

cyrano : tu sors des notions d'algo très vraies.... En théorie. Après tu ne sais pas comment ton compilo va implanter ton code, il peut par exemple être capable de beaucoup optimiser quelque chose de lent en théorie (bon ya des limites bien sur...)

Mais bon, c'est vrai qu'il vaut mieux avoir recours aux listes chainées quand c'est vraiment adéquat (piles, files, etc...)

Sinon c'est pas parce que tu utilises des pointeurs que tu fais de la liste chainée : en C, la notation char tab[] est effectivement équivalente à char* tab.

bon, un newbe qui sait un peu, c'est vraiment dure à convaincre :) 

En sémantique, un tableau est équivalent à un pointeur sur le 1er élements, c'est vrai. tab est équivalent à *(tab+i) (comme pour les tableau les incréments sont multiples de la taille).

D'un point du vue du compilo, cela n'est absolument pas équivalent dans le cas des optimisations. Par exemple :
* a = *aaa;
* b = *bbb;
Est-ce que ce code peut être fait en parrallèle ? oui ? Et bien non, car que se passe-t-il si a == bbb ?

Ensuite, parler de new et de delete quand on parle de C... La glb utilise tout un tas d'astuce qui permet de gagner du temps (allocation par schunk, etc...) qui optimise tout ça.

Sinon je vais casser un rève, un compilo cela n'est pas magique. Il n'accèlère pas du code qui a un algo pourris. Il optimise l'implémentation de l'algo. En général, on dis pouvoir gagner un facteur 10 sur l'implémentation, quand on peut gagner 1000 avec un meilleur algo.

Pour (beaucoup) plus d'info, lire :
http://madchat.org/coding/c/hack_processeur_en_C.html

D'abord, je te prierai de faire preuve de modestie et d'humilité vis à vis des gens. Apparemment être un bourrin en optimisation C, ca n'apprend pas le savoir-vivre.

Qui a dit qu'un compilo était magique ? Je disais ca pour sous entendre que certains algos étaient excellents en théorie, mais posaient des problèmes d'implantation, alors que d'autres peuvent être un peu plus lents (en théorie), et être accélérés parce qu'il collent bien à la gestion de mémoire de ton langage. Et note que je parle en termes d'éventualité, et de généralité.

Et à vrai dire, ca ne me fait ni chaud ni froid que tab ne soit pas équivalent à *(tab+i) au niveau du compilateur. La seule chose que je vois, c'est que c'est équivalent sémantiquement, et que dans les deux cas c'est de la mémoire contigue. Donc aucune comparaison possible avec une liste chainée.
Lassé par la pub ? Créez un compte