Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 28/06/2017, à 12: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 smile

Donut

Dernière modification par DonutMan75 (Le 29/06/2017, à 10:29)

Hors ligne

#2 Le 28/06/2017, à 20: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, à 07: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 smile

Donut

Hors ligne

#4 Le 29/06/2017, à 08: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, à 08: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, à 10: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 smile

Bonne journée à tous,

Donut

Hors ligne

#7 Le 29/06/2017, à 13:17

grigouille

Re : [RESOLU] [C] Addition de pointeurs

De rien.


Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne