Pergunta

Com cordas c-estilo, como você atribuir um char para um endereço de memória que o ponteiro aponta personagem? Por exemplo, no exemplo abaixo, eu quero mudar num para "123456", então eu tentei conjunto p para o dígito onde '0' está localizado e tento substituí-lo com '4'. Obrigado.

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char* num = (char*)malloc(100);
    char* p = num;

    num = "123056";

    p = p+3;    //set pointer to where '4' should be
    p = '4';

    printf("%s\n", num );

    return 0;
}
Foi útil?

Solução

Esse código não vai funcionar, simplesmente porque a linha:

num = "123056";

muda num a ponto de distância da memória alocada (e restos p apontando para o que a memória para que eles não o mesmo local está) à memória o que é mais provável somente leitura. Você não tem permissão para alterar a memória pertencente ao strings literais, é um comportamento indefinido.

Você precisa do seguinte:

#include <stdio.h>
#include <stdlib.h>
int main (void) {
    char *num = malloc (100); // do not cast malloc return value.
    char *p = num;

    strcpy (num, "123056");   // populate existing block with string.

    p = p + 3;                // set pointer to where '0' is.
    *p = '4';                 // and change it to '4'.

    printf ("%s\n", num );    // output it.

    return 0;
}

Outras dicas

Em primeiro lugar, quando você faz:

num = "123056";

Você não está copiando a string "123056" para a área de pilha alocada por malloc(). Em C, a atribuição de um ponteiro char * um valor literal de cadeia é equivalente a defini-lo como uma constante - isto é, idêntico ao:

char str[] = "123056";

Então, o que você acabou realizado lá é que você abandonou a sua única referência para a área de pilha a 100 bytes alocados por malloc(), razão pela qual o seu código posterior não imprime o valor correto; 'p' ainda aponta para a área de pilha alocada por malloc() (desde num apontou para ele no momento da atribuição), mas num não faz mais.

Eu suponho que você realmente pretende fazer era cópia a string "123056" para essa área heap. Veja como fazer isso:

strcpy(num, "123056");

Embora, isso é melhor prática para uma variedade de razões:

strncpy(num, "123056", 100 - 1);  /* leave room for \0 (null) terminator */

Se você tinha acabado de fazer:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int     main(void) {
        char    *num = malloc(100);
        char    *p = num;

        strncpy(num, "123056", 100 - 1);

        p = p + 3;
        *p = '4';

        printf("%s\n", num);

       return 0;
} 

Você teria conseguido o resultado correto:

123456

Você pode contrair esta operação:

p = p + 3;
*p = '4';

... e evitar a iteração do ponteiro, por deferencing da seguinte forma:

*(p + 3) = '4';

Algumas outras notas:

  • Embora a prática estilística comum, lançando o valor de retorno de malloc() para (char *) é desnecessário. Conversão e alinhamento do tipo void * é garantida pela linguagem C.

  • Sempre verifique o valor de retorno de malloc(). Será NULL se a alocação de pilha falhou (ou seja, você está fora de memória), e nesse ponto seu programa deve sair.

  • Dependendo da implementação, a área de memória alocada por malloc() pode conter lixo obsoleto em determinadas situações. É sempre uma boa idéia para zero-lo após a alocação:

    memset(num, 0, 100);
    
  • Nunca se esqueça de free() sua pilha! Neste caso, o programa vai sair e o sistema operacional irá limpar o seu lixo, mas se você não adquirir o hábito, você terá vazamentos de memória em nenhum momento.

Então, aqui está a "melhor prática" versão:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int     main(void) {
        char    *num, *p;

        /*
         * Don't take 1-byte chars for granted - good habit to get into.
         */

        num = malloc(sizeof(char) * 100);

        if(num == NULL)
                exit(1);

        memset(num, 0, sizeof(char) * 100);

        p = num;

        strncpy(num, "123056", 100 - 1);

        *(p + 3) = '4';

        printf("%s\n", num);

        free(num);

        return 0;
}

Além dos p emitir outros * apontaram, você também tem problemas de uso de memória. Você tem um buffer de 100 bytes, com conteúdo desconhecido. Tem um outro tampão de bytes 7, contendo a sequência "123056" e um terminador nulo. Você está fazendo isso:

  1. num é definido como ponto para o buffer de bytes 100
  2. p é definido para apontar para num; ou seja, que aponta para o 100 byte buffer
  3. repuser num para apontar para o buffer de 7 byte; p ainda está a apontar para o tampão de byte 100
  4. Você usar p para modificar o buffer de 100 bytes
  5. então você usa num imprimir o tampão 7 byte

Então você não está imprimindo o mesmo tampão que você está modificando.

Bem, você sabe p é tipo de ponteiro. Ele armazena o endereço do char '0'. Se você atribuir p o valor de '4'. Levará '4' como o endereço. No entanto, o endereço de '4' é ilegal. Você pode usar '*' operador para obter o valor do endereço que está armazenado em p armazenado.

Apenas uso *p = '4'; ...!

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