Domanda

I & # 8217; ho il seguente codice:

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

Questo compila e funziona, cioè. stampa bar, bar. Ora vorrei dimostrare che ciò che accade qui non è copiare una stringa. Vorrei cambiare b e mostrare che a cambia anche. Ho trovato questo semplice codice:

#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; ma segfault. Perché? La cosa interessante è che la seguente modifica funziona bene:

#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;
}

Perché non & # 8217; t segfault come il precedente? Immagino che mi manchi qualche differenza importante tra l'inizializzazione della stringa in stile puntatore e quella in stile array.

È stato utile?

Soluzione

Non puoi cambiare le costanti di stringa, che è ciò che ottieni quando usi la sintassi da puntatore a letterale come nei primi esempi di codice.

Vedi anche questa domanda: È una stringa letterale in c ++ creato nella memoria statica? .

Altri suggerimenti

Quando scrivi questo:

char *b = "bar";

il compilatore alloca un'area di memoria anonima (senza nome) per memorizzare la stringa letterale " bar " ;. I valori letterali di stringa non possono essere modificati, quindi il compilatore (con l'aiuto del linker e del sistema operativo) inserisce il valore letterale di stringa in una parte dello spazio di memoria del programma in esecuzione che è protetto da scrittura. Quando si tenta di modificarlo, il sistema operativo lo rileva e provoca un errore di segmentazione del programma.

(Il tuo codice è C ++, non C, ma è irrilevante per questa domanda.)

Quando scrivi:

char *foo = "bar";

Ciò che realmente accade è che " bar " è memorizzato nel segmento di sola lettura della memoria. Pertanto, è immutabile. Ottieni un segfault perché provi a modificare un segmento di sola lettura.

Puoi anche mostrare che 'a' è stato modificato stampando il valore del puntatore.

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

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

Questo stamperà l'indirizzo a cui 'a' e 'b' indicano.
Devi lanciare 'void *' perché l'operatore & Lt; & Lt; è sovraccarico per 'char *' per stampare la stringa che qualsiasi altro puntatore stamperà l'indirizzo.

In teoria, una stringa letterale non dovrebbe essere in grado di essere assegnata a un carattere *, ma solo un 'carattere costante *'. Quindi il compilatore ti fermerebbe prima di scrivere il codice di errore seg.

Questa differenza è forse specifica del compilatore. Per dimostrare il tuo punto usa malloc per allocare il buffer, quindi copia la stringa in questo buffer e non dimenticare di usare gratuitamente quando non hai più bisogno della stringa.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top