Pages : 1
#1 Le 28/06/2017, à 11:07
- DonutMan75
[RESOLU] [C] Addition de pointeurs
Bonjour à tous.
Dites j'aimerais faire un petit point avec vous concernant les opérations d'addition de pointeurs.
Ma question principale ici est : lorsque x est un pointeur, quand a-t-on le droit de faire l'opération x+1 ???
D'après-moi cette opération est licite dans deux cas seulement :
1) x pointe vers un élément d'un tableau
char *x[10];
Auquel cas :
x = l'adresse de son premier élément (x = &x[0])
x+1 = l'adresse de l’élément suivant (x+1 == &x[1])
2) x est initialisé via un appel à calloc(NBLK, SBLK) qui alloue une zone mémoire de NBLK blocs de SBLK taille
x = calloc(NBLK, SBLK);
x = adresse du premier bloc
x+1 = adresse du bloc suivant
Le code ci-dessous, de mon cru, créé un tableau de NBLK pointeurs T = [p1, p2,..., pN]
Chaque Pk pointe vers une zone mémoire de SBLK octets.
Afin que ce soit formateur, je me suis interdit l'utilisation des notations T[k] et préfère plutôt l'expression *(T+k)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NBLK 10 // Nombre de bloc
#define SBLK 103 // Taille des blocs
int main(void)
{
int k;
void **T = NULL;
T = calloc(NBLK, sizeof(void *));
for(k=0; k<NBLK; k++)
{
*(T+k) = malloc(SBLK);
memset(*(T+k), 0, SBLK);
}
fprintf(stdout, "T = %p\n", T);
for(k=0; k<3; k++)
{
fprintf(stdout, "T+%d \t= %p\n", k, T+k);
fprintf(stdout, "*(T+%d) \t= %p\n", k, *(T+k));
fprintf(stdout, "*(T)+%d \t= %p\n", k, *(T)+k);
}
}
Voici un exemple d’exécution :
$ ./test_alloc
T = 0x8440008
T+0 = 0x8440008
*(T+0) = 0x8440038
*(T)+0 = 0x8440038
T+1 = 0x844000c
*(T+1) = 0x84400a8
*(T)+1 = 0x8440039
T+2 = 0x8440010
*(T+2) = 0x8440118
*(T)+2 = 0x844003a
Si je comprends bien ce que j'obtiens :
T contient l'adresse mémoire qui contient le premier élément de T (donc ici le pointeur *(T+0)).
T+k contient l'adresse mémoire où est stocké le pointeur qui pointe vers la k-ème zone mémoire de taille SBLK
Les incréments mémoire lorsqu'on passe de T+k à T+k+1 sont de 4 octets. Je suppose que ça représente la taille mémoire nécessaire pour stocker un pointeur sur *void ?
*(T+k) contient le pointeur qui pointe vers la k-ème zone mémoire de taille SBLK.
Ces valeurs ont été attribuées par malloc. Il n'y a aucune garantie que ces emplacements soient contigus.
On remarque en effet que le saut entre *(T+1) et *(T+0) est de 60 alors que *(T+2)-*(T+1) ne vaut que 20.
*(T)+k est extrémement dangereux !!
*(T) nous donne l'adresse du premier bloc de donnée
*(T)+k va juste parcourir l'énorme zone mémoire attribuée par calloc(NBLK, SBLK), OCTET PAR OCTET.
J'ai bon ?
Merci d'avance
Donut
Dernière modification par DonutMan75 (Le 29/06/2017, à 09:29)
Hors ligne
#2 Le 28/06/2017, à 19:25
- grigouille
Re : [RESOLU] [C] Addition de pointeurs
Voici un exemple qui montre que T+k ne pointe pas forcement sur un élément d'un tableau :
$ cat toto.c
#include <stdio.h>
int * copy(int *start, int *end, int *res) {
while(start != end) {
*res = *start;
++res;
++start;
}
return res;
}
void print(int *start, int *end) {
while(start != end) {
printf("%d ", *start++);
}
}
int main() {
int t[5] = {5,6,7,8,9};
int u[7];
u[0] = u[1] = 100;
copy(t, t+5, u+2);
print(t, t+5);
printf("\n");
print(u, u+7);
printf("\n");
}
$ ./toto
5 6 7 8 9
100 100 5 6 7 8 9
Debian (xfce) 12
HP LaserJet M1132 MFP
Hors ligne
#3 Le 29/06/2017, à 06:06
- DonutMan75
Re : [RESOLU] [C] Addition de pointeurs
Hello grigouille,
merci pour ta réponse.
Néanmoins, même si je crois avoir compris ton programme je ne saisis pas ta conclusion "un exemple qui montre que T+k ne pointe pas forcement sur un élément d'un tableau".
Ici t et u sont des tableaux d'entier. Donc t+k (avec 0 <= k <= 5) et u+k (avec 0 <= k <= 7) pointent bien vers des éléments des tableaux t et u non ?
Merci pour ce programme en tout cas
Donut
Hors ligne
#4 Le 29/06/2017, à 07:03
- grigouille
Re : [RESOLU] [C] Addition de pointeurs
t+5 n'est pas un élément du tableau t. C'est l'adresse de l'élément juste après le tableau.
Elle permet de délimiter le tableau. On peut utiliser t+5 en tant qu'adresse mais (t+5)* en lecture ou en écriture est une erreur.
De manière générale :
Si p est un pointeur de type T* et si p pointe sur un élément d'un tableau d'objet de type T, alors
- p+1 pointe sur l'élément suivant de ce tableau
- p-1 pointe sur l'élément précédent de ce tableau (à ne pas faire si p est le début du tableau)
- la valeur entière de p+1 est plus grande de sizeof(T) que celle de p.
Debian (xfce) 12
HP LaserJet M1132 MFP
Hors ligne
#5 Le 29/06/2017, à 07:26
- grigouille
Re : [RESOLU] [C] Addition de pointeurs
Un autre exemple que tu pourras méditer :
$ cat tata.c
#include <stdio.h>
int main() {
int ti[5];
short ts[5];
printf("%p %p %zu %zu\n", ti, ti+1, (ti+1)-ti, (char*)(ti+1) - (char*) (ti));
printf("%p %p %zu %zu\n", ts, ts+1, (ts+1)-ts, (char*)(ts+1) - (char*) (ts));
return 0;
}
$ ./tata
0x7fff59384bd0 0x7fff59384bd4 1 4
0x7fff59384bc0 0x7fff59384bc2 1 2
$
Sur ma machine, sizeof(int) = 4 et sizeof(short) = 2.
Debian (xfce) 12
HP LaserJet M1132 MFP
Hors ligne
#6 Le 29/06/2017, à 09:29
- DonutMan75
Re : [RESOLU] [C] Addition de pointeurs
Bonjour gribouille,
super exemple, merci beaucoup !!
Ca permet de vérifier plein de choses sur les additions de pointeurs en peu de lignes
Bonne journée à tous,
Donut
Hors ligne
#7 Le 29/06/2017, à 12:17
- grigouille
Re : [RESOLU] [C] Addition de pointeurs
De rien.
Debian (xfce) 12
HP LaserJet M1132 MFP
Hors ligne