ce post tient plus de l'information que d'un problème. En effet, en lisant le livre de Bjarne Stroustrup sur le c++, j'ai appris a ma grande surprise page 101 que ce code n'est pas valide :
char* s="Bonjour";
s[3]='N';
"Bonjour" est un pointeur (ça c'est normal), mais le truc moins évident (mais évident après coup) c'est que le tableau pointé par s est constant (et statique qui plus est) donc on a aps le droit de le modifier.
En C j'ai souvent utilisé ce genre d'instructions, mais c'est invalide !
Si vous avez des commentaires
EDIT: Pour les débutants, je post le code valide quand même
char s[8]="Bonjour";
s[3]='N';
(Ici "Bonjour n'est plus un pointeur mais le synonyme de {'B','o','n','j','o','u','r','\0'})
RE-EDIT: Le code tout en haut ne marche pas non plus en C (c'est vraiment bizarre que je n'ai jamais fait attention à ça !) : erreur de segmentation
on demande que l'adresse de s soit égale à la premiere adresse d'une suite d'espace mémoire contigüe de taille char. la suite de longueur inconnue se termine par '\0'.
"blabla" est une constante littérale (un const char[])
Les deux déclarations font normalement exactement la même chose
La seule difference qu'il pourait y avoir c'est quand tu met un chiffre plus grand que 8, plus de mémoire sera reservée par ton programme et tu pourra dépasser la chaine de quelques chars sans crainte (pour lire et pour ecrire)
Alors que pour le cas sois disant invalide, ça ne reservera que ce qu'il faut, donc si tu dépasse, il y'a une chance que tu atteigne la mémoire d'un autre programme et la , bonjour le plantage.
Mais je ne comprend pas que ça ne marche pas chez toi, c'est quoi ton compilateur ?
Je vais essayer voir si je dis pas de conneries tiens
Je parle pour le C, mais cela devrait être valable en C++.
Citation : 3D-lite.
Les deux déclarations font normalement exactement la même chose
Comme l'auteur le dit lui-même, les deux déclarations n'ont pas le même effet. Déjà, déclarer un pointeur ou un tableau n'est pas la même chose en général (excepté comme paramètres d'une fonction par exemple). Ensuite, "n'importe quoi" est une chaîne littérale, un objet de type (char []), dont seul l'accès en lecture est possible. L'exception à l'usage des chaînes littérales est l'initialisation de tableaux de caractères, soit la seconde forme employée par l'auteur du topic.
Citation
si tu dépasse, il y'a une chance que tu atteigne la mémoire d'un autre programme et la , bonjour le plantage.
Comme l'auteur le dit lui-même, les deux déclarations n'ont pas le même effet. Déjà, déclarer un pointeur ou un tableau n'est pas la même chose en général (excepté comme paramètres d'une fonction par exemple). Ensuite, "n'importe quoi" est une chaîne littérale, un objet de type (char []), dont seul l'accès en lecture est possible. L'exception à l'usage des chaînes littérales est l'initialisation de tableaux de caractères, soit la seconde forme employée par l'auteur du topic.
Jusqu'a present, pour moi, un "objet char[]" n'etait qu'un pointeur vers de la mémoire allouée normalement, aprés je peux me tromper, peut etre que le compilateur ajoute une "protection" selon les cas.
Citation
Citation
si tu dépasse, il y'a une chance que tu atteigne la mémoire d'un autre programme et la , bonjour le plantage.
Le DOS est mort depuis longtemps.
Je parlais d'un plantage du programme, pas de l'OS heing
Jusqu'a present, pour moi, un "objet char[]" n'etait qu'un pointeur vers de la mémoire allouée normalement, aprés je peux me tromper, peut etre que le compilateur ajoute une "protection" selon les cas.
T D[] déclare un tableau, pas un pointeur. Regarde une des nombreuses références à ce sujet que tu pourras trouver un peu partout sur les tableaux != pointeurs.
Citation
Citation
si tu dépasse, il y'a une chance que tu atteigne la mémoire d'un autre programme et la , bonjour le plantage.
Le DOS est mort depuis longtemps.
Je parlais d'un plantage du programme, pas de l'OS heing ^^</citation>
Non, mais les programmes ne partagent pas lamême mémoire sur les systèmes modernes, donc "écrire sur la mémoire d'un autre programme" n'est pas pertinent dans ce cas.
J'ajoute pour la simple culture générale que la raison pour laquelle le code posté plus haut est valide est qu'il fallait garder la compatibilité avec le C.
En effet, en C il est courant d'écrire:
void func(char *);
func("abc");
Si cette exception n'existait pas, il est probablement que beaucoup de code C ne compilerait pas sans modifications.
Non, mais les programmes ne partagent pas lamême mémoire sur les systèmes modernes, donc "écrire sur la mémoire d'un autre programme" n'est pas pertinent dans ce cas.
A ce que je crois, chaque adresse est unique dans toute la mémoire vive
exemple: le programme 1 alloue de la memoire de l'octet 2900 a 3000 et le programme 2 alloue de 3001 a 3100.
Si le programme 1 déborde, il accedede a l'octet 3001, et la, l'OS est obligé d'arreter le programme 1 non ?
NB: ce que vient de dire pamaury c'est justement le genre de chose qui me fait dire que tableau=pointeur...
Quoi qu'il en soit, ceux qui ont inventé le C ne sont pas clairs
Je réctéfie deux choses:
-oui dans la mémoire vive, une adresse est unique mais dans les OS actuels on utilise ce que l'on appèle la pagination qui fait que l'on peut isoler physiquement un processus d'un autre et lui faire croire qu'il a 4Gio d'espace d'adresses alors qu'en fait non. Regarde sur Wikipédia par exemple, çà sera plus clair.
-non, tableau!=pointeur mais il faut faire attention de quoi l'on parle. Par exemple, il est clair que:
char *p1="str";// bon c'est pas valide comme code mais tant pis char p2[4]="str";
sont deux objets différents, puisque p1 est un pointeur vers la chaîne constante "str" alors que p2 est un tableau QUE L'ON PEUT MODIFIER qui est initialiser à "str":
-la première alloue sizeof(char*) octets pour stocker un pointeur(p1)
-la second alloue 4*sizeof(char) octets pour stocker "str" et p2 pointe vers cette zone
La confusion vient du fait-à mon avis-que en effet, p1 et p2 sont deux pointeurs en un sens mais qui ne pointent pas du tout vers le même type de stockage, p1 pointe vers du stockage en lecture-seule alors que p2 pointe vers du stockage en lecture-écriture.
L'autre confusion vient mon avis du fait que l'on passe en paramètre toutes les chaînes de caractères par pointeur même si c'est un tableau.
> Quoi qu'il en soit, ceux qui ont inventé le C ne sont pas clairs
La norme est claire là-dessus.
La confusion pointeur/tableau vient du fait que dans quasiment tous les cas, une _expression_ de type tableau dégénère en pointeur.
> En effet, en C il est courant d'écrire:
Il était surtout courant dans le temps. Mais tu as raison sur le fait que la plupart des programmeurs C n'accordent pas une importance primodiale aux qualificateurs, s'ils peuvent aider, tant mieux, sinon, tant pis.
-la première alloue sizeof(char*) octets pour stocker un pointeur(p1)
-la second alloue 4*sizeof(char) octets pour stocker "str" et p2 pointe vers cette zone
Il me semble avoir lu que la taille d'un pointeur en mémoire est identique à la taille d'un int
Encore un mythe...
Plus sérieusement, non et le contre exemple est simple:
sur une plateforme 64-bit, un pointeur fait 8 octets et un int 4 octets et un long 8 octets. A priori la taille d'un pointeur n'a rien à voir avec la taille d'un int.
Je confirme : sous 64 bits, un pointeur fait toujours 8 octets.
Mais alors pour les int et les long, je dirais qu'un seul mot : C'EST LA MERDE !!!!!!!!!
Il existe 3 versions différentes de Linux pour le 64 bits : le LP64, le LLP64 et le ILP64 : regardez le lien ci dessous : le tableau dans la 2e partie...
Sous Windows en revanche (testé sous XP64 et Vista 64), ils ont accordé leur violons : nous sommes dans une équivalence LLP64 (toujours 32 bits pour int et long)
-la première alloue sizeof(char*) octets pour stocker un pointeur(p1)
-la second alloue 4*sizeof(char) octets pour stocker "str" et p2 pointe vers cette zone
Mhhh c'est quand même bizarre de modifier de la mémoire sans l'allouer (ou alors il la désalloue juste aprés la déclaration)
Mais sinon un pointeur n'est qu'une adresse donc "sizeof(char*)" ou "sizeof(double*)" ça reviendrais au même non ?
Certes oui la taille d'un pointeur ne varie à priori pas avec le type pointé. Pour ce qui est de la taille alloué, la première déclaration en elle-même n'alloue pas "str", celle-ci est stockée en général dans une section lecture-seule de l'exécutable(j'aurais dû le préciser) alors que la second alloue bien 4 octets sans aucune exception.
Par exemple, si on fait:
Alors les allocations sont:
-"str" est placée dans une section lecture-seule de l'exécutable
-p1 est alloué(sizeof(char*)) et pointe vers "str" alloué dans la section lecture-seule
-p2 est alloué(sizeof(char*)) et pointe vers le même "str" de la section lecture-seule (les compilateurs détectent lorsque l'on réutilise les même chaînes litérales)
-p3 est alloué(4*sizeof(char*)) et est remplie avec {'s','t','r','\0'}
-p4 est alloué(4*sizeof(char*)) et est remplie avec {'s','t','a','\0'}
Evidemment, on remarquera qu'il est extremmement dangereux de laisser p1 et p2 pointer vers de la mémoire en lecture seule mais c'est ainsi que çà marche, normalement on devrait mettre "const char *".
> Certes oui la taille d'un pointeur ne varie à priori pas avec le type pointé.
Rien ne garantie ça. Cela pourrait varier, par exemple, du fait de l'alignement, certains types ayant des adresses exprimées en multiples de leur alignement et non d'octets. En revanche, en C tous les types de pointeurs vers des struct ont même représentation (et donc taille). Une règle équivalente existe pour les union.
> (les compilateurs détectent lorsque l'on réutilise les même chaînes litérales)
Rien ne les obligent mais la majorité le font.
Pour l'alignement, je n'était pas en train de dire que les pointeurs AVAIENT la même taille, j'ai dis qu'ils avaient A PRIORI la même taille(je dis çà car sur la plupart des architecture la taille d'un pointeur ne varie pas).
Sur quelle(s) architecture(s) est-ce que l'on stocke des pointeurs exprimés en multiples de leur alignement ?
Rien ne les obligent mais la majorité le font.
Pour l'alignement, je n'était pas en train de dire que les pointeurs AVAIENT la même taille, j'ai dis qu'ils avaient A PRIORI la même taille(je dis çà car sur la plupart des architecture la taille d'un pointeur ne varie pas).
Sur quelle(s) architecture(s) est-ce que l'on stocke des pointeurs exprimés en multiples de leur alignement ?
Personnellement, je n'ai jamais eu l'occasion de travailler sur tant d'archis que ça mais sur c.l.c ils en parlent d'expérience, parfois. Enfin, c'étaient des précisions, rien de plus.
Bon bin merci beaucoup pour ce débat parce que la différence entre un char* et un char[] m'était toujours restée en travers de la gorge, j'ai toujours eu l'impression qu'il y avait quelque chose de pas clair avec les chaînes de caractères. Je continue de le penser, mais ça va quand même bien mieux
Le saviez-vous... ??
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html