bonjour,
y'a t-il une différence de vitesse de lecture écriture entre la syntaxe pointeur ou tableau ?
Code:
1
2
3 *(tabl+i) // ou tabl[i]
Version imprimable
bonjour,
y'a t-il une différence de vitesse de lecture écriture entre la syntaxe pointeur ou tableau ?
Code:
1
2
3 *(tabl+i) // ou tabl[i]
Aucune. Dans les 2 cas, le compilo se place sur tabl et décale de i éléments.
Là où ça peut jouer, c'est dans un truc de ce genre
Code:
1
2
3
4
5 for (i=0; i < n; i++) tabl[i]=...; for (i=0, pt=tabl; i < n; i++, pt++) *pt=...;
Dans la première boucle, l'opération "positionnement au début et décalage" se fait à chaque itération.
Dans la seconde boucle, ces deux opérations n'y sont plus, le pointeur étant déjà sur le bon élément...
merci
ne pas oublier de remettre le pointeur au debut apres sinon tu vas droit vers le resultat inattendu au mieux et vers Seg default au pire.
on s'est pass compris. soit un pointer p,je fais :
a la fin de ce code si je fais un printf("%d",*p) j'ai aucune des valeurs de i dans [0;4[Code:
1
2
3
4
5
6 for(i=0;i<4;i++) { *p=i; p++; }
donc je lui demande apres le p++ deplacer le pointer jusqu'a ca position de depart
donc faire autant de p-- qu'il faut.
j'ai pas parler d'initialiser le pointeur
Ok. Donc je présume que là, tu remplis les 4 cases d'un tableau. On va donc compléter ton code pour lui rajouter son contexte (sa raison d'exister quoi)...
Code:
1
2
3
4
5
6
7
8 int tab[4]; int *p; p=tab; for (i=0; i<4; i++) { *p=i; p++; }
Puis on lui applique une petite optimisation d'écriture...
Code:
1
2
3
4
5
6 int tab[4]; int *p; for (p=tab, i=0; i<4; i++, p++) { *p=i; }
Exact, p se trouve maintenant sur l'adresse &tab[4] ce qui est une case trop loin...
Et pourquoi tu déplaces p à sa position de départ ? Parce que tu te prépares à traiter le contenu du tableau, style
Donc ce n'est pas après avoir rempli le tableau que tu replaces le pointeur, mais avant de le traiter. Parce que déplacer p jusqu'à sa position de départ (ou n'importe où ailleurs) sans utiliser ensuite ce p ça ne sert pas à grand chose :roll:Code:
1
2
3
4 for (p=tab, i=0; i<4; i++, p++) { printf("La case [%d] vaut %d\n", i, *p); }
Mouais 8O. Ou alors réinitialiser le pointeur (le replacer à sa position de départ) ça marche aussi...
Tu as parlé (qui s'écrit au participe passé et non à l'infinitif) de "remettre" le pointeur au début, autrement dit lui "remettre" une valeur "initiale", autrement dit "initialiser" (ou "réinitialiser") le pointeur... :roll: :roll:
Accessoirement, tu as fait aussi erreur sur la conclusion. Au mieux tu as un SEG_FAULT ce qui arrête le programme ce qui t'indique immédiatement qu'il y a un truc qui cloche dans ton dernier bout de code, au pire tu as un programme qui te renvoie n'importe quoi mais qui tourne quand-même et, si t'as pas trop fait attention, tu peux mettre un paquet de temps avant 1) de voir qu'il y a un problème et 2) trouver le problème enfoui dans un code qui sera, quand tu t'en rendras compte, vieux de quelques jours (ou quelques semaines)...
effectivement en te lisant ainsi et d'ailleur en lisant le post initial j'ai totalement tord.
et j'ai mal exprime ma pensee:
je n'ai jamais compris l'utilite dans ce genre de cas de(question implicite:mrgreen:)Code:int *p=tab
disons que je pensais plus a
dans ce cas en voulant acceder aus donnees on doit retrouver l'adresse donne par malloc, et c'est de ca que je parlais. mais bon si j'avais bien lu le p=tab initial j'aurai pas eu a commenter.Code:p=(T *)malloc(sizeof(T)*4+1);
tu me diras ca non plus je ne l'aurai pas fait car je n'en vois pas l'utilite.bref tout ca pour dire expliquer ce que signifie remetre le pointeur a ca position "initiale" implicitement apres le malloc si on s'amuse a faire de p++. hors sujet j'en conviendrai.
pour la conclusion fausse, ben :mrgreen: et :ccool: en te lisans j'ai commence a penser "mais de quoi il parle on dit justement la meme chose" mais apres relecture de mon propre poste:aie: t'as tout a fait raison. Merci pour la correction.
tord de tordu ou tort ??? Pas la peine de répondre. Moi aussi j'ai longtemps fait la faute...
Attention aux priorités. A moins que ton but ne soit d'allouer 4 cases de taille T plus une case de taille char, ton code devrait être écrit ainsi
Exact. Donc avant d'accéder aux données on doit réinitialiser le pointeur. Mais dans ton cas, plutôt que de perdre p pour le retrouver ensuite (en faisant autant de p-- que t'as fait de p++), vaut mieux utiliser deux pointeurs et remplacer p=malloc(...) par tab=malloc(...) ce qui nous ramène en fait à l'exemple du post précédent...Code:p=(T *)malloc(sizeof(T)*(4+1));
desole mais je parle francais que sur le net depuis pres de 6 ans, je commence a oublier un peu l'ecrit. mais c'est sans rancunes.
"attention aux priorites"
je vois pas l'importance dans ce cas. que le plus 1 soit a l'interrieur ou non. car si je me trompe pas le +1 c'est minimum la taille d'une adresse !?
ps: le post precedent a ete edite pendant que tu repondais
Ben non, c'est la taille d'un octet.
Il faut bien comprendre que malloc attend une taille en octets. Car tu lui demandes de te réserver x octets dans la mémoire (qui, elle aussi, ne travaille qu'en octets)
Si tu veux réserver de la taille pour 4 doubles plus un double supplémentaire comme je sais pas, moi, un marqueur de fin, il te faudra alors 5 doubles soit 5 x 8 = 40 octets.
Si tu demandes sizeof(double) * 4 + 1, tu n'en auras que 8 * 4 + 1 soit 33...
pendant qu'on y est,
pourquoi faut-il ce +1 et faut-il juste un debordement oubien faut la taille du type voulout? dans le premier cas (ce que j'ai toujours pense) effectivement un +1 hors parenteses suffirait mais dans le second en effet faut l'inclure dans la multiplication
C'est toi qui gère ton besoin. Si tu veux (N + 1) éléments, alors il faut allouer (N + 1) * sizeof(...). Mais c'est toujours toi qui a besoin de ce +1 pour tes propres raisons donc tu peux pas me demander pourquoi tu as mis "+1"...
Maintenant, peut-être as-tu remarqué que beaucoup de programmeurs demandaient souvent +1 et tu voudrais savoir pourquoi...
C'est tout simplement pour inclure une "sentinelle". Ca permet d'éviter de se trimballer la taille du tableau avec soi.
Exemple simple: tu veux gérer des personnes (nom, age). Tu vas donc
1) commencer par définir ta structure apte à stocker ton élément
Code:
1
2
3
4 typedef struct { char nom[20]; unsigned short age; } t_personne;
2) tu vas ensuite créer et remplir ton tableau
Code:
1
2
3
4
5 t_personne tab[]={ {"toto", 18], {"titi", 22}, {"tutu", 34}, };
Puis, tu passes ton tableau à une fonction qui doit le traiter (l'afficher). Il faut aussi que la fonction reçoive la taille du tableau sinon elle ne saura pas où s'arrêter
Code:
1
2
3
4
5
6
7
8 void affiche(t_personne *tab, size_t n) { size_t i; t_personne *pt; for (i=0, pt=tab; i < n; i++, pt++) printf("Personne [%lu]: Nom[%s], age[%hu]\n", i+1, pt->nom, pt->age); }
Et tu l'appelles de cette façon
Code:affiche(tab, 3)
Et tu feras de même pour toute fonction devant traiter tab. Ensuite, si 3 passe un jour à 4, il te faudra tout reprendre. Bon, il y a le préprocesseur pour ça mais c'est quand-même bien chiant de se trimbaler quand-même la taille de partout.
Donc pour éviter ça, on inclus dans le tableau un élément supplémentaire permettant d'indiquer la fin. Ca peut-être n'importe quoi mais faut pas que ça puisse être une donnée possible. On peut, par exemple, dire ici "marqueur=age à 0". Ce qui donne
Code:
1
2
3
4
5
6 t_personne tab[]={ {"toto", 18], {"titi", 22}, {"tutu", 34}, {"zero", 0}, };
Maintenant, le tableau embarque avec lui automatiquement sa fin. Donc passer sa taille devient inutile puisque les fonctions recevant le tableau sauront où s'arrêter
Code:
1
2
3
4
5
6
7
8 void affiche(t_personne *tab) { size_t i; t_personne *pt; for (pt=tab, i=0; pt->age != 0; pt++, i++) printf("Personne [%lu]: Nom[%s], age[%hu]\n", i+1, pt->nom, pt->age); }
Et tu l'appelles de cette façon
Code:affiche(tab)
Tu utilises d'ailleurs déjà ce marqueur depuis que tu fais du C sans t'en rendre compte car il existe déjà dans les chaines (caractère '\0' marquant la fin et qu'on ne doit pas oublier quand on veut gérer soi-même des chaines). D'ailleurs, pour symboliser ce marqueur, ma structure initiale aurait dû être écrite ainsi
Montrant à tous les autres programmeurs queCode:
1
2
3
4 typedef struct { char nom[20 + 1]; unsigned short age; } t_personne;
1) ma chaine possède 20 caractères significatifs
2) j'ai pas oublié de penser à gérer le marqueur (qu'on appelle plus couramment "sentinelle")
merci d'avoir pris le temps de repondre de maniere si precise, excellent.
bizarre on m'avait ditt il y a longtemps que c'est par mesure de securite mais je savais vraiment pas pourquoi.
maintenant je vais arreter d'ajouter des +1 a malloc sans raison valable et le metre quand j'ai reelement besoin de sentinelle.
encore merci pour l'explication.