Bonsoir,
quelqu'un peut m'expliquer cà, j'ai pas compris: "pointeur-tableau"
Merci de m'aider
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 char *loc, buf[40]; int ch; printf("%d\n", loc-buf);
Bonsoir,
quelqu'un peut m'expliquer cà, j'ai pas compris: "pointeur-tableau"
Merci de m'aider
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 char *loc, buf[40]; int ch; printf("%d\n", loc-buf);
loc est un pointeur c'est-à-dire une variable qui contient une valeur considérée comme un adresse de zone mémoire. La valeur de loc peut varier
buf est un tableau de 40 caractères, c'est-à-dire une variable qui contient une adresse d'une zone mémoire valide de 40 caractères, à la différence de loc, la valeur de buf est fixe (toute la différence entre pointeur et tableau).
En C, on peut calculer la différence entre deux adresses donc loc_buf est un calcul valide.
Maintenant, le problème est que loc n'étant pas initialisé, la valeur de loc-buf n'a aucune signfication.
"La haine seule fait des choix" - Koan Zen
"Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
"Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
Faites du Prolog, ça vous changera les idées !
Ma page Prolog
Mes codes sources commentés
Mon avatar : La Madeleine à la veilleuse de Georges de La Tour
tu déclare un pointeur loc qui est censé contenir un jour ou l'autre l'adresse d'un char ( mais qui pour le moment ne contient rien de significatif puisque tu n'as rien mis dedans) et un tableau buf de 40 char, ce qui signifie que buf est l'adresse du premier objet du tableau.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 char *loc, buf[40]; ... printf("%d\n", loc-buf);
loc - buf n'a pas de sens si :
1- loc n'a pas été initialisé ( ce qui est le cas)
2- loc est initialisé avec une adresse qui ne se base pas sur buf
Sinon , loc-buf est effectivement un entier
Ce code n'a aucune chance de fonctionner.Envoyé par melmouj
- Ce n'est pas une fonction
- Il manque <stdio.h>
- loc n'est pas initialisé
- La difference entre deux adresses est de type ptrdiff_t or %d attend un int. Manque un cast.
- ch n'est pas utilisé.
Maintenant, si la question est "la différence entre les adresses de deux objets appartenant au même tableau a-t-elle un sens", je répond oui. Elle retourne une valeur entière signée de type ptrdiff_t. qui représente un nombre d'éléments. C'est tout simplement une application directe de l'arithmétique des pointeurs.
soit un tableau de 4 int :
l'adresse de l'élément 1 est a + 1.
Code : Sélectionner tout - Visualiser dans une fenêtre à part int a[4];
l'adresse de l'élément 3 est a + 3
Code : Sélectionner tout - Visualiser dans une fenêtre à part int *x = a + 1;
La différence y - x est donc égale à
Code : Sélectionner tout - Visualiser dans une fenêtre à part int *y = a + 3;
d = a + 3 - (a + 1)
d = a + 3 - a - 1
d = 3 - 1
d = 2
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #include <stdio.h> #include <stddef.h> int main (void) { int a[4]; int *x = a + 1; int *y = a + 3; ptrdiff_t d = y - x; printf ("y-x = %d\n", (int) d); return 0; }
Non. 'buf' n'est pas une variable qui contient une adresse (car ce serait alors un pointeur). C'est une variable tableau qui est formée de n éléments consécutifs de même type. Le nom du tableau est une adresse constante qui a le même type que les éléments du tableau, et dont la valeur est l'adresse du premier élément.Envoyé par Trap D
Normal, puisque l'arithmétique des pointeurs nous enseigne que :
buf == &buf[0]
qui s'écrit aussi
buf == buf + 0
et donc
buf == buf
Ok. J'ai mis du temps à comprendre, parce qu'il y a des doubles négations... Plus assez de neurones en état de marche pour ça...Envoyé par diogene
buf est une variable qui contient une adresse d'une zone de mémoire valide, cette valeur est fixe comme je l'ai dit plus loin. Tu reformules ce que j'ai écrit.
"La haine seule fait des choix" - Koan Zen
"Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
"Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
Faites du Prolog, ça vous changera les idées !
Ma page Prolog
Mes codes sources commentés
Mon avatar : La Madeleine à la veilleuse de Georges de La Tour
Trap D :Emmanuel :buf est une variable qui contient une adresseEmmanuel a raison. Ce n'est pas une variable, c'est une valeur. Si c'était une variable, cette valeur serait placée qq part en mémoire (et cette variable serait alors un objet pointeur). En ce qui concerne le tableau, mis à part les objets du tableau, il n'y a rien d'autre en mémoire.Non. 'buf' n'est pas une variable
J'ai dit que la valeur de cette variable est fixe.
Je crois que nous ne sommes pas d'accord sur le sens du terme "variable".
Si je dis que buf est une variable de type tableau ? (comme le dit d'ailleurs aussi Emmanuel) es-tu d'accord ?
"La haine seule fait des choix" - Koan Zen
"Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
"Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
Faites du Prolog, ça vous changera les idées !
Ma page Prolog
Mes codes sources commentés
Mon avatar : La Madeleine à la veilleuse de Georges de La Tour
Je le prend dans le sens "variable" <->"objet"Je crois que nous ne sommes pas d'accord sur le sens du terme "variable".
Je dis simplement que l'identificateur buf désigne une valeur du type adresse de qq chose. Je suis très réservé sur le fait de parler d'un objet (variable) tableau pour la raison qu'il n'existe aucun opérateur (dynamique, donc mis à part & et sizeof qui sont résolus à la compilation) susceptible de s'appliquer à cet "objet". On ne peut manipuler que les objets du tableau (pas même les éléments du tableau à cause des tableaux à plusieurs dimensions)Si je dis que buf est une variable de type tableau ? (comme le dit d'ailleurs aussi Emmanuel) es-tu d'accord ?
Bien sûr, nous sommes d'accord sur le fonctionnement des tableaux, mais pour moi, conceptuellement, ce n'est pas un objet, c'est un arrangement mémoire d'objets + une syntaxe de manipulation de ces objets
D'accord, il vaut mieux utiliser le terme identificateur plutôt que variable, j'essayerai de m'en souvenir dorénavant![]()
Je rajouterais ceci pour voir si nous nous sommes bien compris :
Au point de vue mémoire qu'a-t-on ?
si on dit char tab[10] en mémoire on a une zone de 10 octets consécutifs, le premier octet a une certaine adresse désignée par tab.
L'identificateur tab désigne l'adresse du premier caractère.
On ne peut donc pas prendre l'adresse de tab, celà n'a aucun sens.
si on dit char *p, en mémoire on a (celà dépend du système) une zone de X octets consécutifs, la valeur de cette zone de X octets est interprétée comme l'adresse d'une autre zone mémoire.
L' identificateur p désigne la zone mémoire,
On peut prendre l'adresse de p, qui désigne le premier caractère de la zone mémoire,
La valeur de p qui est la valeur du nombre contenu dans la zone de mémoire
Enfin *p désigne la valeur de l'objet dont l'adresse est p.
(Peut-être aurais-je du parler de caractères plutôt que d'octets ?)
"La haine seule fait des choix" - Koan Zen
"Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
"Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
Faites du Prolog, ça vous changera les idées !
Ma page Prolog
Mes codes sources commentés
Mon avatar : La Madeleine à la veilleuse de Georges de La Tour
Si 'fixe' signifie constante, c'est donc une valeur constante (comme 123 ou 'X'). Une variable (même const) est un objet. Sa principale caracteristique est d'avoir une adresse. Certes, le tableau à une adresse, mais son type n'est pas celui d'un élément du tableau. L'hypothétique variable de valeur fixe contenat l'adresse du premier élément du tableau n'existe pas. C'est toute la différence entreEnvoyé par Trap D
et
Code : Sélectionner tout - Visualiser dans une fenêtre à part char *s = "hello" ;
Code : Sélectionner tout - Visualiser dans une fenêtre à part char s[] = "hello";Il n'y a pas cinquante définitions du terme variable. Une variable est un objet défini par une adresse et un type.Je crois que nous ne sommes pas d'accord sur le sens du terme "variable".
Oui.Si je dis que buf est une variable de type tableau ? (comme le dit d'ailleurs aussi Emmanuel) es-tu d'accord ?
Et pourtant si : celà n'a aucun sens pour moi aussi, mais on peut.On ne peut donc pas prendre l'adresse de tab, celà n'a aucun sens.
Tab est un type tableau de int, mais dès que Tab est évalué (expression ou passage en paramètre) il prend le type " adresse d'un élément" ici int*
Code : Sélectionner tout - Visualiser dans une fenêtre à part int Tab[4]
Si tu demande sizeof(Tab) tu obtiens 4*sizeof(int)
Si tu demande sizeof(Tab+0) tu obtiens sizeof(int *)
&Tab a la même valeur que Tab mais un autre type : adresse d'un tableau de int : int (*)[]
Alors , pour les tableaux à plusieurs dimensions ....
C'est ce qui fait toute la difficulté des tableaux (surtout à plusieurs dimensions). Il y a l'interprétation du compilateur qui s'écarte de la "réalité physique"
Les tableaux sont compliqués en C mais les pointeurs, c'est simple!!!![]()
Oui.Envoyé par diogene
C'est bien un objet en ce sens qu'il a une adresse et un type. La définiton de tableau nous enseigne qu'il s'agit d'un type agrégé formé de plusieurs objets identiques placés consécutivement en mémoire.Je suis très réservé sur le fait de parler d'un objet (variable) tableau pour la raison qu'il n'existe aucun opérateur (dynamique, donc mis à part & et sizeof qui sont résolus à la compilation) susceptible de s'appliquer à cet "objet". On ne peut manipuler que les objets du tableau (pas même les éléments du tableau à cause des tableaux à plusieurs dimensions)
Bien sûr, nous sommes d'accord sur le fonctionnement des tableaux, mais pour moi, conceptuellement, ce n'est pas un objet, c'est un arrangement mémoire d'objets + une syntaxe de manipulation de ces objets
de 10 char (objets de taille >= 8bits)Envoyé par Trap D
Non. C'est l'adresse de tab qui est la même que l'adresse du premier char. (&tab[0] ou tab + 0 ou tab).le premier octet a une certaine adresse désignée par tab.
Si tu veux dire 'du premier char, oui.L'identificateur tab désigne l'adresse du premier caractère.
Si. tab est aussi un objet avec une adresse et un type. Le type est 'tableau de 10 char'. L'adresse a donc le type pointeur sur tableau de 10 char et s'exprime aunsi :On ne peut donc pas prendre l'adresse de tab, celà n'a aucun sens.
char (*p)[10] = &tab;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <stdio.h> int main (void) { char tab[10]; char (*p)[10] = &tab; tab[2] = 'x'; printf ("'%c'\n", tab[2]); printf ("'%c'\n", (*p)[2]); printf ("sizeof tab = %u\n", (unsigned) sizeof tab); printf ("sizeof *p = %u\n", (unsigned) sizeof *p); return 0; }Si elle est correctement initialisée, oui.si on dit char *p, en mémoire on a (celà dépend du système) une zone de X octets consécutifs, la valeur de cette zone de X octets est interprétée comme l'adresse d'une autre zone mémoire.
Il désigne à la fois le pointeur (la variable) et son contenu. Ca dépend du contexte. Mais pas l'objet pointé.L' identificateur p désigne la zone mémoire,
Disons le premier byte, oui. Mais un pointeur n'est pas un tableau. C'est un objet composé d'un certain nombre de bytes (2, 4 ...)On peut prendre l'adresse de p, qui désigne le premier caractère de la zone mémoire,
Ca, c'est l'adresse de l'objet pointé...La valeur de p qui est la valeur du nombre contenu dans la zone de mémoire
Oui, c'est le fameux opérateur * de déréférencement.Enfin *p désigne la valeur de l'objet dont l'adresse est p.
Non. On parle de char ou plus généralement de bytes. Dans la spec du C? sizeof retourne la taille d'un objet en bytes.(Peut-être aurais-je du parler de caractères plutôt que d'octets ?)
Un caractère, c'est une valeur constante (de type int) qui désigne un glyphe (le dessin du caractère) associé à une valeur numérique qui dépend du charset. Par exemple, en ASCII, le glyphe '0' a pour valeur 0x30 (48 en décimal).
La norme prévoit que la valeur d'un caractère est comprise entre 0 et 255 inclus.
Emmanuel :Pour moi, cet "objet" a une valeur (qui est une adresse) et un type. Il n'a pas une véritable adresse à lui. Si on dit que son adresse est l'adresse du premier objet du tableau, on se retrouve avec deux objets différents, ( l' "objet" tableau el le premier objet du tableau) à un même emplacement mémoire. Cette exception choque mon esprit logiqueC'est bien un objet en ce sens qu'il a une adresse et un type.(on peut évoquer les unions mais le cas est différent)
oui, un type agrégé, pas un objet agrégéLa définiton de tableau nous enseigne qu'il s'agit d'un type agrégé formé de plusieurs objets identiques placés consécutivement en mémoire
Tout celà obéit à une logique non évidente, d'où le retour périodique de ce débat. La complexité n'est pas liée au tableau à 1 dimension, mais c'est l'introduction des tableaux à plusieurs dimensions qui a imposé ces complications
Emmanuel :N'y a t'il pas là contradiction ?Citation:
le premier octet a une certaine adresse désignée par tab.
Non. ............
Citation:
L'identificateur tab désigne l'adresse du premier caractère.
........... oui.
Bien sûr que si, ça a du sens. Imaginons qu'on veuilles allouer dynamiquement un tableau de n lignes de 80 caractères :Envoyé par diogene
Voici un pointeur sur une ligne de 80 caractères utiles:
si je fais
Code : Sélectionner tout - Visualiser dans une fenêtre à part char (*p_line)[80+1];
j'alloue une ligne. Je peux ecrire dedans comme ça :
Code : Sélectionner tout - Visualiser dans une fenêtre à part p_line = malloc (*p_line);
ou
Code : Sélectionner tout - Visualiser dans une fenêtre à part strcpy (*p_line, "Hello world");
Maintenant si je veux allouer 10 lignes, je fais :
Code : Sélectionner tout - Visualiser dans une fenêtre à part strcpy (p_line[0], "Hello world");
et je peux faire ceci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part p_line = malloc (*p_line * 10);
Illustration :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 strcpy (p_line[2], "Hello"); strcpy (p_line[8], " world");
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 #include <stdlib.h> #include <string.h> #include <stdio.h> int main (void) { char (*p_line)[80 + 1]; p_line = malloc (sizeof *p_line); if (p_line != NULL) { strcpy (*p_line, "Hello world"); printf ("*p_line = '%s'\n", *p_line); strcpy (p_line[0], "Hello world"); printf ("p_line[0] = '%s'\n", p_line[0]); free (p_line), p_line = NULL; } p_line = malloc (sizeof *p_line * 10); if (p_line != NULL) { strcpy (p_line[2], "Hello"); strcpy (p_line[8], " world"); printf ("p_line[2] = '%s'\n", p_line[2]); printf ("p_line[8] = '%s'\n", p_line[8]); free (p_line), p_line = NULL; } return 0; }
On parle tableau et là tu nous parles pointeur, je ne vois rien qui va contre le sens de ce que dit Diogène :
Envoyé par Diogène
"La haine seule fait des choix" - Koan Zen
"Il ne faut pas être meilleur que les autres, il faut être meilleur que soi." Albert Jacquard
"Ceux qui savent où ils ont posé leur parapluie ne sont pas alcooliques." - pgibonne.
Faites du Prolog, ça vous changera les idées !
Ma page Prolog
Mes codes sources commentés
Mon avatar : La Madeleine à la veilleuse de Georges de La Tour
Non. La valeur d'un tableau n'est pas une adresse. Comme pour tout objet agrégé, cet objet n'a pas de valeur propre. Seuls les objets 'simples' on une valeur. Dans un tableau, il s'agit de chaque élément du tableau. Autre objet agrégé, une structure : La notion de valeur appliquée à une structure n'a aucun sens. La différence est que le nom d'une structure ne renefrme pas l'adresse de son premier élément, alors que c'est le cas avec les tableaux. C'est une conséquence directe de l'arithmétique des pointeurs et de la garantie apportée par le langage qui dit qu'un tableau débute à l'adresse de son premier élément.Envoyé par diogene
Simplement, il existe une adresse constante qui a la valeur et le type du premier élément du tableau, et dont l'identificateur est le même que le nom du tableau. Cette facilité apparente du langage entretient l'illusion que le nom du tableau est l'adresse du tableau.
tab != &tab
d'ailleurs, n'importe quel compilateur bien né signalera une erreur de type si on cherche à les comparer.
Oh que si ! (Si ça peut te rassurer, j'ai aussi mis du temps à l'admettre !)Il n'a pas une véritable adresse à lui.
L'analogie avec l'union n'est pas absurde. On peut en effet considérer que d'une part on a un objet agrégé de type tableau de n x T, et 'en parallelle', une séquence de n objets simples de type T identiques et consécutifs.Si on dit que son adresse est l'adresse du premier objet du tableau, on se retrouve avec deux objets différents, ( l' "objet" tableau el le premier objet du tableau) à un même emplacement mémoire. Cette exception choque mon esprit logique(on peut évoquer les unions mais le cas est différent)
Je ne vois rien de choquant là dedans, et il se peut que je reprenne cette analogie si je formalise tout ça un jour...
Un type agrégé est formé de l'aggrégation de plusieurs objets simple ou agrégés de même type ou non.oui, un type agrégé, pas un objet agrégéLa définiton de tableau nous enseigne qu'il s'agit d'un type agrégé formé de plusieurs objets identiques placés consécutivement en mémoire
Emmanuel :Pas d'accord. Une structure est un objet (aggrégé) qui a une valeur en soi (l'ensemble des valeurs de ses membres) : la preuve est qu'on peut copier une structure dans une autre par assignation qui donne à l'objet à gauche de = la Valeur de celui placé à droite. Parce qu'il existe cet opérateur sur les structures, je reconnais sans hésiter à une structure le statut d'objetAutre objet agrégé, une structure : La notion de valeur appliquée à une structure n'a aucun sens.
On est d'accord sur le fonctionnement des tableaux et tout ça peut sembler très académique mais ce qui se comprend bien s'énonce clairement et on n'en est pas là. Notre discussion, c'est aussi une question de vocabulaire différent. Voici le mien en résumé :
un objet a une existence physique en mémoire donc il a une adresse. Il a une valeur, et il a un type (celui de sa valeur).
Le type détermine les opérations susceptibles de s'appliquer à l'objet. Si il n'existe pas d'opérateur, on ne peut manipuler l'objet (comme un tout), ce n'est pas un objet (maiss c'est peut être une collection d'objets, je veux bien)
C'est pourquoi, bien que comprennant parfaitement ce que tu veux dire, la phrasene me plait pas beaucoup : un type formé d'objets. J'aime mieux un objet formé d'objetsUn type agrégé est formé de l'aggrégation de plusieurs objets
Et cette formalisation n'est pas évidente, puisqu'on en discute abondamment. Et c'est l'absence d'une formalisation claire qui place (ou non) les tableaux dans la logique des autres grandeurs du C qui rend les tableaux complexes.si je formalise tout ça un jour...
Je t'incite donc à entreprendre cette réflexion et surtout à nous faire part de son résultat![]()
Partager