Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

chaîne de caractères et pointeur

7 réponses
Avatar
prat
Bonjour,

j'ai vu =E9cris dans un algorithme en langage C quelque chose comme
ceci:

char *
mois[11]=3D{"Janvier","F=E9vrier",,"Mars","Avril","Mai","Juin","Juillet","A=
out","Septembre","Octobre","Novembre","D=E9cembre"};

c'est un tableau de pointeurs de caract=E8res.
chaque element du tableau est donc un pointeur de caract=E8res.Il y en a
12.

Ma question est:
Pourquoi un pointeur de caract=E8re peut =EAtre assimil=E9 =E0 une cha=EEne
de caract=E8res?
Je sais qu'un tableau est aussi un pointeur mais un pointeur peut-il
=EAtre un tableau?Si oui,cela expliquerait qu'un pointeur de caract=E8res
est un tableau de caract=E8res donc une cha=EEne de caract=E8res.

merci.

7 réponses

Avatar
Pierre Maurette
Bonjour,

j'ai vu écris dans un algorithme en langage C quelque chose comme
ceci:

char *
mois[11]={"Janvier","Février",,"Mars","Avril","Mai","Juin","Juillet","Aout","Septembre","Octobre","Novembre","Décembre"};


Plusieurs erreurs. Essayez de poster du code compilable et lisible.
char* mois[]={"Janvier", "Février", "Mars",
"Avril", "Mai", "Juin",
"Juillet", "Aout", "Septembre",
"Octobre", "Novembre", "Décembre"};

Et si vous voulez donner la taille du tableau, c'est 12, pas 11. Mais
il ne faut pas la donner. Vous pouvez l'obtenir par:
sizeof tableau / sizeof tableau[0]


c'est un tableau de pointeurs de caractères.
chaque element du tableau est donc un pointeur de caractères.Il y en a
12.


Oui. "Mars" est un pointeur constant. Il pointe vers une chaine, dans
une zone de données initialisées. Donc à priori non modifiable.

Ma question est:
Pourquoi un pointeur de caractère peut être assimilé à une chaîne
de caractères?


Parce que la représentation en C d'une chaine de caractères est un
tableau de char terminée par ''.

Je sais qu'un tableau est aussi un pointeur mais un pointeur peut-il
être un tableau?Si oui,cela expliquerait qu'un pointeur de caractères
est un tableau de caractères donc une chaîne de caractères.


Un tableau est un tableau. Mais le nom de ce tableau, en particulier
lors d'un passage en argument, est remplacé par un pointeur, l'adresse
du premier élément du tableau, qu'on peut appeler l'adresse du tableau.

char tab[12];
est un tableau de 12 char (peut contenir une chaîne de 11 lettres)
modifiables. Initialisé ou non selon l'endroit où il est déclaré.

char tab[12] = "trouduc";
est un tableau de 12 char (peut contenir une chaîne de 11 lettres)
modifiables. Initialisé par les lettres de "trouduc" et complété dans
tous les cas par des ''.

char* grosMot = "trouduc";
est un pointeur (modifiable) initialisé par le pointeur constant vers
la chaîne "trouduc".


Essayez de jouer avec ce code, et voyez si ça vous apporte quelque
chose chose:

int main(void)
{
char* mois[]={"Janvier", "Février", "Mars",
"Avril", "Mai", "Juin",
"Juillet", "Aout", "Septembre",
"Octobre", "Novembre", "Décembre"};
char* mars = "Mars";


printf("%lun", sizeof mois / sizeof mois[0]);
printf("%s - %p - %pn",
mois[2] == mars ? "Optimise" : "Optimise pas",
mois[2],
mars);
mois[0] = "January";
puts(mois[0]);
/*
moi[1] = 'f';
puts(mois[1]);
*/
return 0;
}

Le résultat du deuxième printf() peut dépendre de votre compilateur. La
première ligne des deux lignes commentées devrait sur beaucoup de
compilateurs provoquer un plantage par violation d'accès.

--
Pierre Maurette

Avatar
Pascal Bourguignon
"prat" writes:

Bonjour,

j'ai vu écris dans un algorithme en langage C quelque chose comme
ceci:

char *
mois[11]={"Janvier","Février",,"Mars","Avril","Mai","Juin","Juillet","Aout","Septembre","Octobre","Novembre","Décembre"};

c'est un tableau de pointeurs de caractères.
chaque element du tableau est donc un pointeur de caractères.Il y en a
12.


Donc ça ne compilera pas sans erreur...


Ma question est:
Pourquoi un pointeur de caractère peut être assimilé à une chaîne
de caractères?


Parce que c'est la définition que le langage C donne à "chaîne de
caractère". Un pointeur vers le premier "caractère" de la chaîne. Il
donne aussi une étrange définition à "caractère": un entier qui tient
dans exactement une case mémoire (définie comme étant l'unité de
mémoire adressable).

'A' est un entier. Dont la valeur bien sur dépend de l'encodage
utilisé pour le source du programme, tel que défini par le
compilateur, en général c'est de l'ASCII et ça vaut donc 65.

"ABC" est un pointeur vers un vecteur contenant 4 "caractères": 65,
66, 67 et 0, stockés à dans les cases mémoires aux adresses "ABC"+0,
"ABC"+1, "ABC"+2 et "ABC"+3.


Je sais qu'un tableau est aussi un pointeur mais un pointeur peut-il
être un tableau?


Oui. C'est à dire, qu'un pointeur peut pointer vers un élément d'un
tableau (note que comme on ne peut avoir que des tableaux de 1
dimension, ce sont en fait des vecteurs), et qu'aussi bien pour une
variable de type "tableau" ou de type "pointeur" on peut utiliser les
mêmes opérations:

char v[10];
char* p=v;

*(p+3), *(v+3), 3[p], 3[v], p[3], v[3], *(3+p), *(3+v) désignent tous
la même case mémoire.


Si oui,cela expliquerait qu'un pointeur de caractères
est un tableau de caractères donc une chaîne de caractères.



Mais il y a une différence importante dont il faut toujours tenir
compte: un pointeur peut pointer vers d'autre cases mémoire. C'est un
peu comme si un vecteur était en fait un pointeur constant: il pointe
toujours vers le même bloc de mémoire. Un pointeur variable peut
pointer vers des blocs de mémoire alloués statiquement ou
dynamiquement, ou peut aussi contenir une adresse illégale.



--
__Pascal Bourguignon__ http://www.informatimago.com/

"This machine is a piece of GAGH! I need dual Opteron 850
processors if I am to do battle with this code!"

Avatar
Pierre Maurette
(supersedes )

Bonjour,

j'ai vu écris dans un algorithme en langage C quelque chose comme
ceci:

char *
mois[11]={"Janvier","Février",,"Mars","Avril","Mai","Juin","Juillet","Aout","Septembre","Octobre","Novembre","Décembre"};


Plusieurs erreurs. Essayez de poster du code compilable et lisible.
char* mois[]={"Janvier", "Février", "Mars",
"Avril", "Mai", "Juin",
"Juillet", "Aout", "Septembre",
"Octobre", "Novembre", "Décembre"};

Et si vous voulez donner la taille du tableau, c'est 12, pas 11. Mais
il ne faut pas la donner. Vous pouvez l'obtenir par:
sizeof tableau / sizeof tableau[0]


c'est un tableau de pointeurs de caractères.
chaque element du tableau est donc un pointeur de caractères.Il y en a
12.


Oui. "Mars" est un pointeur constant. Il pointe vers une chaine, dans
une zone de données initialisées. Donc à priori non modifiable.

Ma question est:
Pourquoi un pointeur de caractère peut être assimilé à une chaîne
de caractères?


Parce que la représentation en C d'une chaine de caractères est un
tableau de char terminée par ''.

Je sais qu'un tableau est aussi un pointeur mais un pointeur peut-il
être un tableau?Si oui,cela expliquerait qu'un pointeur de caractères
est un tableau de caractères donc une chaîne de caractères.


Un tableau est un tableau. Mais le nom de ce tableau, en particulier
lors d'un passage en argument, est remplacé par un pointeur, l'adresse
du premier élément du tableau, qu'on peut appeler l'adresse du tableau.

char tab[12];
est un tableau de 12 char (peut contenir une chaîne de 11 lettres)
modifiables. Initialisé ou non selon l'endroit où il est déclaré.

char tab[12] = "trouduc";
est un tableau de 12 char (peut contenir une chaîne de 11 lettres)
modifiables. Initialisé par les lettres de "trouduc" et complété dans
tous les cas par des ''.

char* grosMot = "trouduc";
est un pointeur (modifiable) initialisé par le pointeur constant vers
la chaîne "trouduc".


Essayez de jouer avec ce code, et voyez si ça vous apporte quelque
chose chose:

int main(void)
{
char* mois[]={"Janvier", "Février", "Mars",
"Avril", "Mai", "Juin",
"Juillet", "Aout", "Septembre",
"Octobre", "Novembre", "Décembre"};
char* mars = "Mars";


printf("%un", sizeof mois / sizeof mois[0]);
printf("%s - %p - %pn",
mois[2] == mars ? "Optimise" : "Optimise pas",
mois[2],
mars);
mois[0] = "January";
puts(mois[0]);
/*
mois[1][0] = 'f';
puts(mois[1]);
*/
return 0;
}

Le résultat du deuxième printf() peut dépendre de votre compilateur. La
première ligne des deux lignes commentées devrait sur beaucoup de
compilateurs provoquer un plantage par violation d'accès.

--
Pierre Maurette

Avatar
Radamanthe
prat wrote:
Bonjour,

j'ai vu écris dans un algorithme en langage C quelque chose comme
ceci:

char *
mois[11]={"Janvier","Février",,"Mars","Avril","Mai","Juin","Juillet","Aout","Septembre","Octobre","Novembre","Décembre"};
^^^^ ^^

[12] ,

C'est tiré du K&R non ?

c'est un tableau de pointeurs de caractères.
chaque element du tableau est donc un pointeur de caractères.Il y en a
12.

Ma question est:
Pourquoi un pointeur de caractère peut être assimilé à une chaîne
de caractères?


Parce-qu'en C, une chaîne est une suite de caractères en mémoire dont
l'adresse du premier est dans le pointeur de la chaîne.

char *p = "test";

p <--- pointeur
|
[0] [1] [2] [3] [4] <--- adresse
't' 'e' 's' 't' '' <--- contenu

Je sais qu'un tableau est aussi un pointeur mais un pointeur peut-il
être un tableau?


char *p;

p est un pointeur, mais ne pointe pour l'instant sur rien de valide.

p = malloc(1 * sizeof(char)); /* == 1 */

Maintenant p pointe sur un tableau de 1 caractère.

Je sais qu'un tableau est aussi un pointeur mais un pointeur peut-il
être un tableau?Si oui,cela expliquerait qu'un pointeur de caractères
est un tableau de caractères donc une chaîne de caractères.


p[0] = '';

Maintenant p est aussi une chaîne vide.


--
R.N.

Avatar
Radamanthe
Radamanthe wrote:
Maintenant p est aussi une chaîne vide.


Maintenant p pointe aussi sur une chaîne vide.


--
R.N.

Avatar
prat
On 21 jan, 19:24, Radamanthe wrote:
Radamanthe wrote:
Maintenant p est aussi une chaîne vide.Maintenant p pointe aussi sur une chaîne vide.


--
R.N.


Autre question:
si char*p; est utilisé pour désigner une chaîne de
caractères,c'est-à-dire un tableau de caractères
int*p; ne serait-il pas équivalent au même titre à un tableau
d'entiers de telle sorte qu'il serait possible de l'initialiser comme
ceci?
int*p={1,2,3,4};

ou comme ceci?
p[0]=1;
p[1]=2;
p[2]=3;
p[3]=4;


Avatar
Pierre Maurette

On 21 jan, 19:24, Radamanthe wrote:
Radamanthe wrote:
Maintenant p est aussi une chaîne vide.Maintenant p pointe aussi sur une
chaîne vide.


--
R.N.


Autre question:


J'aime beaucoup votre sens subtil de la politesse. C'est moderne.

si char*p; est utilisé pour désigner une chaîne de
caractères,c'est-à-dire un tableau de caractères
int*p; ne serait-il pas équivalent au même titre à un tableau
d'entiers de telle sorte qu'il serait possible de l'initialiser comme
ceci?
int*p={1,2,3,4};


Vous avez mal lu les réponses. Vous pouvez écrire:
char* p = "petrus";
parce que "petrus" est une constante chaîne de caractère, c'est à dire
un pointeur constant pointant vers une zone non modifiable
(éventuellement en ROM dans de l'embarqué par exemple, pour que ce soit
clair) contenant les six lettres suivies de ''.

Quand vous écrivez:
char tab[] = "petrus";
vous avez un tableau de 7 char initialisé par petrus et ''.

Mais si vous faites:
char* p = {'p','e','t','r','u','s'};
ou
char* p = {'p','e','t','r','u','s',''};
vous initialisez p à la tentative de conversion en pointeur de l'int de
valeur 'p'. Le reste est ignoré, warning prévisible.

Pour les entiers c'est pareil:
int p[] = {1,2,3,4};
fait ce qu'on attend.
int* q = {1,2,3,4};
initialise q à la conversion de 1 en pointeur, éventuellement l'adresse
0x0000000000000001. Le reste est ignoré et ça doit ouarner.

ou comme ceci?
p[0]=1;
p[1]=2;
p[2]=3;
p[3]=4;


Comme ceci il n'y a pas de problème.

--
Pierre Maurette