Différence entre char *str=“STRING” et char str[] = “CHAÎNE”?
Lors de l'encodage d'une simple fonction pour supprimer un caractère particulier dans une chaîne, je suis tombé sur cette étrange question:
void str_remove_chars( char *str, char to_remove)
{
if(str && to_remove)
{
char *ptr = str;
char *cur = str;
while(*ptr != 'void str_remove_chars( char *str, char to_remove)
{
if(str && to_remove)
{
char *ptr = str;
char *cur = str;
while(*ptr != '\0')
{
if(*ptr != to_remove)
{
if(ptr != cur)
{
cur[0] = ptr[0];
}
cur++;
}
ptr++;
}
cur[0] = '\0';
}
}
int main()
{
setbuf(stdout, NULL);
{
char test[] = "string test"; //stack allocation?
printf("Test: %s\n", test);
str_remove_chars(test, ' '); //works
printf("After: %s\n",test);
}
{
char *test = "string test"; //non-writable?
printf("Test: %s\n", test);
str_remove_chars(test, ' '); //crash!!
printf("After: %s\n",test);
}
return 0;
}
')
{
if(*ptr != to_remove)
{
if(ptr != cur)
{
cur[0] = ptr[0];
}
cur++;
}
ptr++;
}
cur[0] = 'void str_remove_chars( char *str, char to_remove)
{
if(str && to_remove)
{
char *ptr = str;
char *cur = str;
while(*ptr != '\0')
{
if(*ptr != to_remove)
{
if(ptr != cur)
{
cur[0] = ptr[0];
}
cur++;
}
ptr++;
}
cur[0] = '\0';
}
}
int main()
{
setbuf(stdout, NULL);
{
char test[] = "string test"; //stack allocation?
printf("Test: %s\n", test);
str_remove_chars(test, ' '); //works
printf("After: %s\n",test);
}
{
char *test = "string test"; //non-writable?
printf("Test: %s\n", test);
str_remove_chars(test, ' '); //crash!!
printf("After: %s\n",test);
}
return 0;
}
';
}
}
int main()
{
setbuf(stdout, NULL);
{
char test[] = "string test"; //stack allocation?
printf("Test: %s\n", test);
str_remove_chars(test, ' '); //works
printf("After: %s\n",test);
}
{
char *test = "string test"; //non-writable?
printf("Test: %s\n", test);
str_remove_chars(test, ' '); //crash!!
printf("After: %s\n",test);
}
return 0;
}
Ce que je ne comprends pas est pourquoi le deuxième test échoue?
Pour moi, il ressemble à la première notation char *ptr = "string";
est équivalent à celui-ci: char ptr[] = "string";
.
N'est-ce pas le cas?
- Très bon article sur ce sujet: eli.thegreenplace.net/2009/10/21/...
- Lire: la Différence entre
char *str
etchar str[]
et comment les deux magasins dans la mémoire?
Vous devez vous connecter pour publier un commentaire.
Les deux déclarations ne sont pas les mêmes.
char ptr[] = "string";
déclare un char tableau de taille7
et l'initialise avec les personnagess
,t
,r
,i
,n
,g
et\0
. Vous êtes permis de modifier le contenu de ce tableau.char *ptr = "string";
déclareptr
comme un pointeur de char et l'initialise avec l'adresse de littéral de chaîne"string"
qui est en lecture seule. La modification d'un littéral de chaîne est une comportement indéfini. Ce que vous avez vu(seg fault) est une manifestation du comportement indéfini.char *ptr = "string";
laptr
peut être précisé à autre chose, et peut à cet effet être "changé" en ce qu'elle montre, mais les personnages"string"
est un littéral et ne peut pas changer.sizeof(ptr)
n'est pas la longueur du tableau, à moins queptr
est déclarée comme un tableau de char. Siptr
est défini comme un int arryay avec 3 éléments,sizeof(ptr)
sera de retour à la somme desizeof(int)
de chaque élément.À proprement parler une déclaration de
char *ptr
seulement vous garantit un pointeur vers le type de caractère. Il n'est pas inhabituel pour la chaîne pour former une partie du segment de code de l'application compilée qui serait définie en lecture seule par certains systèmes d'exploitation. Le problème réside dans le fait que vous faites une hypothèse sur la nature de la pré-définis chaîne (qu'il est accessible en écriture), alors qu'en fait, vous n'avez jamais explicitement créé à la mémoire de cette chaîne vous-même. Il est possible que certaines implémentations de compilateur et de système d'exploitation vous permettra de faire ce que vous avez tenté de le faire.D'autre part, la déclaration de
char test[]
, par définition, en fait alloue lisible et accessible en écriture de la mémoire pour le tableau d'ensemble des caractères sur la pile dans ce cas.char *test = "string test";
est mauvais, il doit avoir étéconst char*
. Ce code compile tout simplement parce que de l'arrière comptables raisons. La mémoire pointée parconst char*
est une mémoire en lecture seule et à chaque fois que vous essayez d'écrire, il va invoquer un comportement indéfini. D'autre partchar test[] = "string test"
crée un écriture tableau de caractères sur la pile. Ce comme n'importe quel autre regualr variable locale à laquelle vous pouvez écrire.test
point à modifiable chaîne, et de garder un drapeau (dans une autre variable) indiquant qu'il a été remplacé par quelque chose de modifiable. Encore, dans la plupart des cas, il est probablement une bonne pratique à utiliserconst
là.Aussi loin que je me souvienne
crée un copie de
"string"
sur la pile, donc il est mutable.La forme
est juste la compatibilité descendante pour les
et vous n'êtes pas autorisé (en termes de comportement indéfini) à toute modification de son contenu.
Le compilateur peut placer ces chaînes en lecture seule section de la mémoire.
Bonne réponse @codaddict.
Aussi, un
sizeof(ptr)
vous donnera des résultats différents pour les différentes déclarations.Le premier, celui de la déclaration de tableau, sera de retour la longueur du tableau dont le caractère de fin null.
La seconde,
char* ptr = "a long text...";
sera le retour de la longueur d'un pointeur, généralement de 4 ou 8.est bon code et crée une mutable chaîne. str est affecté à une mémoire dans le tas, la valeur de "test" rempli en elle.