Question

J'ai & # 8217; j'ai le code suivant:

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;
    cout << a << ", " << b << endl;
    return 0;
}

Ceci compile et fonctionne, c.-à-d. imprime bar, bar. J'aimerais maintenant démontrer que ce qui se passe ici ne copie pas une chaîne. J'aimerais changer b et montrer que a change également. Je suis venu avec ce code simple:

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;
    b[1] = 'u'; // ← just this line added
    cout << a << ", " << b << endl;
    return 0;
}

& # 8230; mais il segfaults. Pourquoi? La chose intéressante est que la modification suivante fonctionne très bien:

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char b[] = "bar"; // ← declaration changed here
    a = b;
    b[1] = 'u';
    cout << a << ", " << b << endl;
    return 0;
}

Pourquoi & # 8217; n'est-il pas une erreur de segmentation identique à la précédente? Je suppose qu'il me manque une différence importante entre le style de pointeur et l'initialisation de chaîne de style tableau.

Était-ce utile?

La solution

Vous ne pouvez pas modifier les constantes de chaîne, ce que vous obtenez lorsque vous utilisez la syntaxe pointeur à littéral comme dans les premiers exemples de code.

Voir aussi cette question: est un littéral de chaîne en c ++ créé en mémoire statique? .

Autres conseils

Quand vous écrivez ceci:

char *b = "bar";

le compilateur alloue une zone de mémoire anonyme (sans nom) pour stocker le littéral de chaîne & "bar &"; Les littéraux de chaîne ne pouvant pas être modifiés, le compilateur (à l'aide de l'éditeur de liens et du système d'exploitation) place le littéral de chaîne dans une partie de l'espace mémoire du programme en cours protégé en écriture. Lorsque vous essayez de le modifier, le système d'exploitation le détecte et cause une erreur de segmentation dans votre programme.

(Votre code est C ++, pas C, mais cela n'a aucune importance pour cette question.)

Lorsque vous écrivez:

char *foo = "bar";

Ce qui se passe réellement, c’est que la & "; barre &"; est stocké dans le segment en lecture seule de la mémoire. Par conséquent, il est immuable. Vous obtenez une erreur de segmentation parce que vous essayez de modifier un segment en lecture seule.

Vous pouvez également montrer que "a" a été modifié en imprimant la valeur du pointeur.

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;

    cout << (void*)a << ", " << (void*)b << endl;
}

Ceci imprimera l'adresse où pointent 'a' et 'b'.
Vous devez utiliser 'vide *' parce que l'opérateur & Lt; & Lt; est surchargé pour 'char *' pour imprimer la chaîne, tout autre pointeur imprimera l'adresse.

En théorie, un littéral de chaîne ne devrait pas pouvoir être affecté à un caractère *, mais uniquement à un 'caractère constant *. Ensuite, le compilateur vous arrêterait avant que vous écriviez du code défectueux.

Cette différence est peut-être spécifique au compilateur. Pour illustrer votre propos, utilisez malloc pour allouer le tampon, puis copiez la chaîne dans ce tampon et n'oubliez pas d'utiliser free lorsque vous n'avez plus besoin de la chaîne.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top