Tout d'abord, pardonnez-moi si c'est une question naïve; Je ne suis qu'un débutant qui essaie d'apprendre.
Je sais que:
char* a = malloc(3*sizeof(char)) ; a = "CD" ; a[0] = 'S' ; // even regular a = "MR"; does not work
Stocke la chaîne dans la mémoire en lecture seule ; donc toute modification des chaînes n'est pas possible. (constante)
Mais je savais que c'était aussi le cas lors de l'utilisation de malloc;
char* a = "CD";
Je suis tellement confus que je pensais que c'était stocké dans le tas ...
Pourquoi ne puis-je pas modifier la chaîne?
4 Réponses :
La bonne façon de procéder est de copier la chaîne: p > a = "CD";
fait exactement la même chose que char * a = "CD";
: il stocke l'adresse du "CD" en
a
. La valeur renvoyée par l'appel à malloc
est écrasée et la mémoire allouée est perdue. strcpy(a, "CD");
Non, vous affectez simplement le pointeur avec l'adresse de la chaîne littérale et l'adresse précédemment stockée de la mémoire mallocée est perdue.
Sident DV-ter - qu'est-ce qui ne va pas dans ma réponse? Ou peut-être que c'est juste la phase de lune
Vous confondez pointeur et allocation:
char *
est un pointeur vers un caractère à un endroit de notre mémoire (il peut ou non être le tas) "CD"
) Bien que le pointeur puisse pointer vers une constante ou un tas, vous pouvez faire la même opération (par exemple: dans votre exemple, attribuez 0 avec 'S'). Cela ne signifie pas que cela fonctionnera toujours au moment de l'exécution: il peut y avoir une certaine protection contre cela.
Pour le pire exemple:
const char* a = "CD" ; a[0] = 'S' ; // should not compile
En utilisant gcc (Gentoo 7.3.0-r3 p1.4) 7.3.0 , et l'exécution du programme, cela a entraîné une erreur de segmentation directement à strcpy
.
Vous ne pouvez utiliser strcpy
que dans la mémoire allouée :
char* a = malloc(3*sizeof(char)); strncpy(a, "EFGHAAAAAAAAAAAA", 3 ); a[2] = 0;
En faisant cela, vous êtes sorti des limites: la mémoire pointée par a peut stocker jusqu'à 3 caractères, ce dernier étant le \ 0 code>.
Dans ce cas, vous devriez (toujours?) utiliser strncpy
à la place:
char* a = malloc(3*sizeof(char)) ; strcpy(a, "EFGHAAAAAAAAAAAA"); // may fail with Segmentation fault printf("a: '%s'\n", a); // print a: 'EFGHAAAAAAAAAAAA'
À côté, vous devriez N'utilisez probablement jamais char *
avec une chaîne constante mais const char *
(le compilateur peut déjà vous avertir à ce sujet, sinon utilisez -Wall
):
char* a = "CD"; char* b = "ZZ"; strcpy(a, "EFGHAAAAAAAAAAAA"); // may fail with Segmentation fault printf("a: %3s, b: %3s\n", a, b); // may not work
mémoire constante, une telle chaîne ("CD")
est fausse. Ce n'est pas un emplacement de mémoire constant. Par exemple, sur les processeurs d'architecture harvard comme les AVR, la chaîne sera finalement située dans la SRAM
Vous avez peut-être raison (j'ai fait du C il y a longtemps et je ne m'en souviens que de ma mémoire inconsistante), mais n'est-ce pas trop compliqué pour les débutants?
strcpy
peut être utilisé sur plus de mémoire allouée. Il peut généralement être utilisé pour un stockage automatique, statique et autre.
Je suis conscient que:
char* a = "CD";Stocke la chaîne dans une mémoire en lecture seule; donc toute modification des chaînes n'est pas possible. (constante)
Cela dépend de la façon dont vous le voyez. La norme C n'impose pas aux littéraux de chaîne de se retrouver en mémoire morte. En fait, la norme C n'exige même pas que le système ait une mémoire morte. Cependant, si vous essayez de modifier une chaîne littérale, le comportement n'est pas défini.
Citation de la norme C11:
Il n'est pas précisé si ces tableaux sont distincts à condition que leurs éléments aient les valeurs appropriées. Si le programme tente de modifier un tel tableau, le comportement n'est pas défini.
Veuillez excuser les fautes d'orthographe
C et C ++ sont différents, choisissez-en un et éditez . Je suppose que vous demandez à C.
Désolé pour ça, je viens de le faire.
Vous jetez la mémoire que vous avez
malloc
éditée et pointez le pointeur vers un littéral en lecture seule.Hors sujet: C'est une bonne idée de toujours assigner des littéraux aux pointeurs
char const *
- cela permet d'éviter UB en raison de la modification de la mémoire immuable via ces pointeurs. Seuls les littéraux ne sont pas const pour des raisons de compatibilité (pour éviter de casser le code existant), carconst
n'existait pas lors de leur invention ...