1
votes

Malloc crée-t-il des constantes de chaîne?

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?


5 commentaires

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), car const n'existait pas lors de leur invention ...


4 Réponses :


6
votes

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.

La bonne façon de procéder est de copier la chaîne: p >

strcpy(a, "CD");


0 commentaires

-1
votes

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.


1 commentaires

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



1
votes

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)
  • mémoire constante telle qu'une chaîne ( "CD" )
  • allocation dynamique dans le tas.

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


3 commentaires

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.



0
votes

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.

https://port70.net/ ~ nsz / c / c11 / n1570.html # 6.4.5p7


0 commentaires