Questions betes : compilo vs runtime et tableaux - C - Programmation
Marsh Posté le 02-12-2004 à 00:20:42
parce que la conversion implicite vers pointeur aurait foutu un sacré bordel je pense
Marsh Posté le 02-12-2004 à 00:51:05
vous devez pas parler de ça je suppose ? (que j'ai découvert recemment seulement )
Code :
|
Marsh Posté le 02-12-2004 à 01:10:20
tiens je viens de voir qu'en compilant le même code avec g++ l'executable était un rien plus gros, pq ?
Marsh Posté le 02-12-2004 à 01:11:22
oui, mais meme encapsulé dans une structure ca reste une l-value
quand tu passe un tableau (son nom) en argument à une fonction, tu passe l'adresse de son premier element, le type attendu est un pointeur sur le type du tableau, cette exception concerne juste les tableaux
de meme pour l'affectation
Marsh Posté le 02-12-2004 à 01:27:39
Taz a écrit : parce que la conversion implicite vers pointeur aurait foutu un sacré bordel je pense |
Oui
En même temps c'est marrant de constater comme au terme de 30 ans d'existence, le C est toujours un langage qui ne fait que le strict minimum.
J'imagine qu'au moment de rédiger la première norme ANSI, il devait y avoir pléthore d'implémentations du langage avec des mécanismes permettant d'avoir un langage moins bas niveau, plus proche du pascal par exemple, il parait meme qu'il y avait des versions avec garbage collector qui connaissaient un certain succès
Mais le C standard est toujours resté fidèle à ses origines : un langage de programmeur système et de developpeurs de compilateurs. Comme il fait peu de chose, forcemment il ne cache pas grand chose et reste performant/facile à porter
Marsh Posté le 02-12-2004 à 01:34:35
push a écrit : tiens je viens de voir qu'en compilant le même code avec g++ l'executable était un rien plus gros, pq ? |
Parce que g++ compile ton code C comme du code C++? (je n'utilise pas g++)
Marsh Posté le 02-12-2004 à 02:08:57
cris56 a écrit : oui, mais meme encapsulé dans une structure ca reste une l-value |
une lvalue c'est une expression de membre gauche qui va prendre une valeur exemple :
char canard[] = "coincoin";
canard -> lvalue
"coincoin" -> rvalue
Un tableau est une lvalue non modifiable c'est à dire qu'avec
int tab[2] = { 1, 2}; // définition et initialisation
le C associe tab à une séquence de caractère contigus en mémoire
tab = { 2, 1};
on tente de permuter les valeurs de tab de la manière dont on l'a initialisé => erreur
Enfin un tableau n'est pas un pointeur, quand tu passes un tableau en paramètre d'une fonction qui attend un pointeur, le tableau est passé comme le reste, par copie, seulement il y a une convertion implicite à faire : le C fait tableau->pointeur qui va contenir l'adresse du premier élément du tableau. Mais amuse toi à définir une variable int prout[]; dans un fichier et à la déclarer à nouveau sous forme de pointeur dans un autre extern int * prout; et observe le résultat .
Marsh Posté le 02-12-2004 à 08:19:10
manatane a écrit : Quelques questions sur la gestion des variables locales et des tableaux dans un programme C. |
Il faut distinguer ce qui est définit par le langage C, et la façon dont les compilateurs implémentent ces définitions.
Vu du langage C, il existe 3 types de mémoire caractérisées par leur durée de vie :
Dans les implémentations (compilateurs C) les plus courantes, la mémoire statique est le segment de données (DATA, BSS), la mémoire automatique est prise dans la pile, et la mémoire allouée est prise dans le tas. Le segment TEXT est généralement l'endroit où se trouve le code exécutable. Ces détails peuvent beaucoup varier d'un compilateur à l'autre.
Citation : |
Pourquoi, je ne sais pas, il faudrait demander à des spécialistes du langage C. Par contre, oui, on peut passer un tableau entier dans une structure, mais est-ce un bon choix?
Faire des copies incessantes de données n'est pas un gage de performance. Même quand on utilise une structure, on s'efforce (comme pour un tableau) de ne passer/retourner l'adresse de celle-ci via un pointeur.
Si on a besoin de l'information 'taille' ou 'nombre d'élements', on passe un paramètre supplémentaire.
Marsh Posté le 02-12-2004 à 08:42:59
manatane> ca va je voulais dire le contraire, un tableau n'est pas une l-value
et tableau != pointeur et conversion implicite &tab[0]->pointeur on en a parlé x fois
Marsh Posté le 02-12-2004 à 13:00:02
Citation : |
En fait, je me suis mal exprimé, je sais -en gros- que le compilateur met les données globales initialisées et les données statiques dans le segment data,
les données globales non initialisées dans bss
et les instructions executables dans text en read only pour générer un executable,
ensuite le loader charge l'executable en mémoire via mmap() par exemple.
Ma question est plutot que beaucoup de manuels disent que les variables locales ne sont pas présentes dans l'executable, or elles y sont forcemment même si ce n'est pas en tant que données.
J'aurais voulu savoir comment le compilateur les traite (mais apparemment comme tu l'as souligné, celà dépend du compilateur et peut etre du format de données elf, coff...), est ce qu'il traite leur définition en tant qu'instruction donc laissé tel quel dans le segment text ou autre
Marsh Posté le 02-12-2004 à 13:08:42
manatane a écrit : Ma question est plutot que beaucoup de manuels disent que les variables locales ne sont pas présentes dans l'executable, or elles y sont forcemment même si ce n'est pas en tant que données. |
Bon, les statiques, on est d'accord, elles vont en BSS ou DATA, et suivant le format, leur nom se retrouve ou pas dans la symtab.
Les autres, bah ça dépend du degré d'optimisation (et si la fonction en appelle d'autres).
Par défaut, une variable locale sera mise dans la pile, puis référencée depuis cet emplacement. Sa présence n'apparait donc que dans le code local, avec des choses comme Registre3=Pile[10].
Si tu optimises, et que la variable n'a pas besoin d'être stockée, alors elle peut ne pas apparaitre. C'est le cas pour les index de boucle "for" par exemple, qui souvent n'existent pas: leur valeur n'est suivie que dans un registre, elle n'est présente nulle part en mémoire.
Marsh Posté le 02-12-2004 à 13:15:22
manatane a écrit : |
C'est vrai. Elle sont créées automatiquement dans la mémoire dite 'automatique'. (En pratique, le plus souvent la pile).
Citation : |
Non. Elle n'y figurent pas du tout. Elles n'ont d'ailleurs pas d'adresse fixe, celle-ci étant définie à l'exécution (et non au chargement comme les adresses des variables statiques).
Citation : |
Dans les cas que je connais (x86, 68k), le processeur dispose d'instructions spécialisées pour créer un 'cadre de pile' qui permet de réserver temporairement (durée de vie de la fonction) une zone de données 'locale'. Les détails sont à voir en désassemblant le code d'entrée et de sortie d'une fonction C. Si les instructions n'existe pas, il est toujours possible de modifier le pointeur de pile 'à la main' pour réserver de la place...
D'ailleurs, les paramètres utilisent aussi une technique similaire.
Important. L'usage de la mémoire automatique n'est pas garanti, et sa taille est limitée. Ca signifie qu'on augmente les risques de crashes majeurs en imbriquant fortement les appels de fonctions, ou par une récursivité trop profonde, ou en définissant des objets automatiques de taille importante (tableaux...). Dans ce dernier cas, la solution est souvent d'utiliser malloc()/free() (la mémoire allouée), même si ce n'est que pour la durée de vie de la fonction.
Marsh Posté le 02-12-2004 à 13:50:22
manatane a écrit : Merci à tous les deux |
Uniquement pour voir les détails. En pratique, on a pas d'assembleur à écrire (saufs cas très spéciaux et très spécialisés...)
Marsh Posté le 02-12-2004 à 14:05:11
Oui
Cà me permettra de mieux comprendre ce que je fais et d'optimiser un peu mieux.
Enfin en restant raisonnable (il vaut mieux un code clair qui sera optimisé par le compilateur plutot qu'un code pénible à lire mais parvenant à gratter quelques cycles j'imagine).
Marsh Posté le 02-12-2004 à 14:33:39
fais du c, pour ne pas faire d'assembleur
http://fr.wikipedia.org/wiki/Langa [...] Assembleur
Marsh Posté le 01-12-2004 à 23:10:07
Quelques questions sur la gestion des variables locales et des tableaux dans un programme C.
Comment le compilateur traite-il t'il les variables locales? Est ce qu'il les zappe en tant que données (variables locales seulement présentes dans le segment _text?)?
Autre question pourquoi un tableau a t'il tant de restriction tel quel? (l-value non modifiable, impossible de le copier dans un autre tableau de meme taille/type, de le passer par valeur à une fonction, d'en faire la valeur de retour d'une fonction) quand ces 3 restrictions peuvent etre gruger simplement en l'encapsulant dans une structure?
Message édité par manatane le 01-12-2004 à 23:12:17