Pergunta

Eu tenho o seguinte código:

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

Este compila e obras, ie. impressões bar, bar. Agora eu gostaria de demonstrar que o que acontece aqui não é copiar uma string. Eu gostaria de mudar b e mostrar que a também muda. Eu vim com este código simples:

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

... mas segfaults. Por quê? O interessante é que a seguinte modificação funciona muito bem:

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

Por que não ele segfault como o anterior? Eu acho que eu estou faltando alguma diferença importante entre o estilo de ponteiro e a inicialização seqüência de estilo matriz.

Foi útil?

Solução

Você não pode mudar as constantes string, que é o que você começa quando você usa a sintaxe ponteiro-to-literal como nas primeiras amostras de código.

Veja também esta pergunta: é um literal de cadeia em c ++ criado em memória estática? .

Outras dicas

Quando você escreve o seguinte:

char *b = "bar";

o compilador aloca uma (sem nome) área de memória anônima para armazenar a string literal "bar". strings literais não podem ser modificados, para que o compilador (com a ajuda do vinculador e sistema operacional) coloca o literal de cadeia em uma parte do espaço de memória do programa em execução que é protegido contra gravação. Ao tentar modificá-lo, as capturas do sistema operacional em que ele e faz com que seu programa para falha de segmentação.

(O código é C ++, não C, mas isso é irrelevante para esta pergunta.)

Quando você escreve:

char *foo = "bar";

O que realmente acontece é que o "bar" é armazenado no segmento de somente leitura de memória. Portanto, é imutável. Você começa um segfault porque você tentar modificar um segmento somente leitura.

Você também pode mostrar que 'a' foi alterado por imprimir o valor do ponteiro.

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

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

Isto irá imprimir o endereço que 'a' ponto e 'b' em.
Você tem que elenco para '* vazio' porque o operador << é sobrecarregado para 'char *' para imprimir a seqüência de qualquer outro ponteiro irá imprimir o endereço.

Em teoria, um literal de cadeia não deve ser capaz de ser atribuído a um char *, apenas uma 'const char *'. Em seguida, o compilador iria pará-lo antes que você escreveu SEG falha código.

Essa diferença talvez seja específico do compilador. Para demonstrar seu uso ponto de malloc para alocar o buffer, em seguida, copiar a cadeia para este buffer e não se esqueça de usar livre quando você não precisa mais do string.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top