Ir para conteúdo
Fórum Script Brasil
  • 0

Diferenças entre tratar ponteiros do tipo char de outros tipos.


victor93

Pergunta

Olá a todos!! Galera, tenho uma dúvida conceitual, primeiro peço que leiam meu código ( é pequeno e serve apenas para explicitar minhas dúvidas):

#include <stdio.h>


int main() {
    
    
    char *p1, vet[]="Coruja";
    int  *p2,  x=6;
    
    p1 = vet; // ou p1=&vet[0],tanto faz
    printf("endereco do ponteiro p1: %x\nendereco da variavel apontada por p1: %x\ncontudo armazenado em p1: %s\n\n\n",p1, &p1, p1);
    
    p2 = &x;
    printf("endereco do ponteiro p2: %x\nendereco da variavel apontada por p2: %x\nvalor armazenado em p2:%d", p2, &p2, *p2);
    
    return 0;
}

DÚVIDAS:

    Por que quando printamos o conteúdo referente a um ponteiro do tipo char, não podemos passar o *p1 como argumento para indicar esse conteúdo? Por exemplo, quando queremos printar o conteúdo apontado por um ponteiro do tipo int, passamos o *p2 como um argumento.Caso eu o fizesse num ponteiro do tipo char, o programa não rodaria.Outra dúvida, o conteúdo armazenado peloponteiro do tipo char p1 e o conteúdo apontado por ele foram passados por mim no printf como o mesmo argumento ( ambos p1),mas um printou o endereço( passei como %x ) e o outro o conteúdo da string (passei como %s). Como pode isso?! É um conteúdo ou um endereço afinal??
    Parece que quanto mais tento estudar ponteiros, mais confuso eu fico...broxante!!

Desde já grato.

 

Editado por victor93
Link para o comentário
Compartilhar em outros sites

1 resposta a esta questão

Posts Recomendados

  • 0

o problema é que você esta estudando ponteiros porem você ainda não aprendeu o que são arrays >_<.

Que é um array? Bom basicamente um array é um conjunto de dados de um mesmo tipo, armazenado na memória de forma consecutiva. Porem para acessar a essa memória, isso acontece mediante um ponteiro implícito. Vamos fazer um desenho do que seria um array de chars em memória, algo simples, algo como "Alo mundo"

//isso é um array de chars, ou seja um string
['A']['l']['o'][' ']['m']['u']['n']['d']['o']['\0']

Isso é um string, um conjunto de dados básicos o tipo char. Até aqui nada novo né, você deve ta pensando... I esse noob que me ta contando kkk

Ok agora vem o divertido. Depois disso você vai entender os arrays como nunca XD
O problema reside que nós não acessamos a todas as variáveis de uma só vez, por exemplo o printf, o unico que quer saber é qual é a primeira letra desse array. Essa letra é 'A' não é? Ai o que é que ele faz? Ele pega vai la na memória bunitinho, imprime a 'A' depois imprime a segunda que esta ao lado que é a 'l'. você reparou que eu marquei em negro "forma consecutiva" lá quando expliquei o que é um array? Então! Na memoria, todas as letras desse array são vizinhas, então o nosso colega "printf" vai imprimindo todas elas uma a uma todas as que estiverem ao lado. Quando é que ele para? quando ele encontrar o NULL que é a ultima, si não ele não saberia onde parar. Ele vai parar no '\0' (Sempre!) Tá.. mais ainda não explicou né? XD Não realmente não explicou! Ainda... XD Vamos pensar... Como você acha que ele acede a cada letrinha??? Fácil! Com um ponteiro!!!

Quando eu crio char vet[]="Coruja"; considere que vet é um ponteiro (Realmente é um ponteiro), que inicia apontando a primeira variável, ele sempre vai apontar a primeira ao inicio. Graficamente seria isso:

*vet
  |
  v
  0   1    2   3   4  5   6
['C']['o']['r']['u']['j']['a']['\0']

Agora acho que já começa entender... Ou não sei kkk. Si já sabia isso, agora vem o que vai fazer você entender melhor.

 vet[0] é isso então:

*vet
  |
  v
  0   1    2   3   4  5   6
['C']['o']['r']['u']['j']['a']['\0']

si eu faço vet[1] troca o ponteiro para a posição 1.

    *vet
      |
      v
  0   1    2   3   4  5   6
['C']['o']['r']['u']['j']['a']['\0']

Isso é o que vai fazendo o printf, ele vai trocando e imprimindo um por um até chegar no Nulo. Por que tem o nulo? Imaginou o que aconteceria si eu fizer char vet[10000]="Coruja"; e somente guardar "Coruja"? Como vai saber printf onde parar? No 10000? kkk Não é arte de magia, é ciência. kkk

Tá vamos deixar de conversa e vamos ao grão. O que é p1 = vet? É uma copia de ponteiro, você esta copiando a direção do ponteiro vet em p1, nada mais!

vamos ver a explicação lógica...
Uma variável guarda um numero, porem um ponteiro apesar de também guardar números, não guarda números qualquer, si não que guarda números de direção.  Agora vamos ver que fazem os operadores de direção (&) e indireção(*).
-O operador de direção (&) serve para manipular direção lógico. Como uma variável esta feita para guardar números si queremos extrair sua direçao devemos por & adiante, ou seja que si eu faço  int ptr= &n; estou guardando em ptr a direçao de n, lógico isso é o que espera ptr(A direçao), mas si eu fizer  int ptr= n; como n guarda um numero, é como si eu fizesse int ptr= *n; no qual o que vai acontecer é que ptr vai guardar o valor de n e não sua direção, isso é errado. Acho que aqui você não tem problema.

O operador de indireção retorna o conteúdo da variável apontada, ou sej, si tenho  int ptr= &n;  e logo faço int n2 = *ptr; estou guardando em n2 o valor de n1.

Ok aqui vem a explicação.
Como sabemos que o que guarda um ponteiro é uma direção si vamos copiar um ponteiro a outro não temos que por o (&) adiante não é? Isso é correto:

char *p1;
char  b = 'w';
char *p2;

p1 = &b; //p1 aponta b

Para copiar o ponteiro p1 em ponteiro p2 nós fazemos:

p1 = p2;  //Ambas apontam a b, tanto p1 como p2

fazer isso p1 = p2 é errado não é?

Então! Isso demonstra que ao fazer p1 = vet é uma copia de ponteiros, agora ambos apontam ao principio do seu string "Coruja".
Logo de fazer p1 = vet

 *p1
  |
  v
  0   1    2   3   4  5   6
['C']['o']['r']['u']['j']['a']['\0']

Fica igual que vet

*vet
  |
  v
  0   1    2   3   4  5   6
['C']['o']['r']['u']['j']['a']['\0']


Por isso você mesmo coloca no comentário do seu código "// ou p1=&vet[0],tanto faz". Ao fazer &vet[0] você esta extraindo a direção da primeira letra do seu array e guardando em p1 hombre! XD

então Agora vou deixar bem claro o que você quer escutar...

Si eu quero imprimir com printf todo um string eu faço:
char vet[]="Coruja";
printf("%s", vet);
Eu não tenho que que por * adiante não é? então... si antes eu falei que ao fazer p1 = vet;, isso é uma copia.... Por que deveria por * adiante de p1 si você não tem que colocar * adiante de vet???? TADAHHH!!!
Entendeu?

Agora vamos responder uma por uma:

-Por que quando printamos o conteúdo referente a um ponteiro do tipo char, não podemos passar o *p1 como argumento para indicar esse conteúdo?
R: isso é por que p1 já é um ponteiro que aponta a primeira posição, printf entende que ao passar p1 o nome p1 é o mesmo que &vet[0], isso é o que espera printf

-Por exemplo, quando queremos printar o conteúdo apontado por um ponteiro do tipo int, passamos o *p2 como um argumento.
R: O tipo de operação é diferente, O mecanismo do printf com array de char eu já expliquei, quando usamos o operador %s ele pega e imprime todas as letras, porem com int ele não imprime todas as letras, si não que temos que indicar uma a uma as que queremos imprimir. recorde que quando copiamos p1 = vet estamos copiando a primeira posição do array, porem o modificador %s atua diferente do modificador %d ou %x ou %c, ele diz "Imprime tudo até o NULL", já o %d por exemplo, diz "imprime essa casinha somente".

-Caso eu o fizesse num ponteiro do tipo char, o programa não rodaria.
R: Claro si você tentar fazer printf ( "%s", *p1 ); o %s ta esperando saber onde esta a primeira letra do string, &vet[0], e você passa *p que imprime a letra 'C' já que ele aponta a primeira letra do vet, ai o programa pega o valor, sei la.. da tabela asc2 equivalente a C e bota ele no %s, será 100 acho, então o printf tenta mandar o ponteiro lá na direção 100 da memória e começar a printar dali. Resultado.... Acho que nosso amigo windows capa isso, por que ele sabe que é uma má idéia, você ta tentando acessar a memória que não te pertence. É o windows quem faz a reserva de memória por nós, quando fazemos char c; estamos pedindo "Windows! Tem memória para um char? Windlws responde.. Sim claro! Nosso programa fala pra ele: Beleza anota aí que é minha kkk" Resultado... o window sabe tuuuudo!!!! XD

-Outra dúvida, o conteúdo armazenado pelo ponteiro do tipo char p1 e o conteúdo apontado por ele foram passados por mim no printf como o mesmo argumento ( ambos p1), mas um print ou o endereço( passei como %x ) e o outro o conteúdo da string (passei como %s). Como pode isso?! É um conteúdo ou um endereço afinal??
R: Acho que isso já ta respondido não? tanto p1 como vet apontam a mesma bagaça. XD

-Parece que quanto mais tento estudar ponteiros, mais confuso eu fico...broxante!!
R: Brocha não... kkk

Desde já grato.
R: (y)

Uff cansei... Fui

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,3k
×
×
  • Criar Novo...