Ir ao conteúdo

C Output de string estranho


Ir à solução Resolvido por JorgeGus,

Posts recomendados

Postado

Bom estou com o seguinte codigo:

#include <stdio.h>
  
int main(void){
	
  	char s[] = "texto";
  	char *c = (char*) &s;
  
  	for(int i=0;i<5;i++){
    	printf("%c", *c + i);
    }
  
	return 0;
}

 

Eu não estou entendendo porque o meu output é "tuvwx" e não "texto". Porque quando eu passo "*c + i" dentro do printf ele deveria andar um byte e printar a segunda string no array.

Usando "puts(c)" ele printa normal a palavra "texto"

  • Membro VIP
Postado

Por isso que eu digo que vetores, ponteiros e afins são pra mim entidades sobrenaturais. Você, caro autor ou membro experiente, consegue explicar passo a passo o que acha que a função deveria fazer?

  Em 31/10/2022 às 02:59, XPointersX disse:
char *c = (char*) &s;
Expandir  

Algo como s= o endereço do conteúdo do endereço ? .. aff

😁

  • Amei 1
  • Solução
Postado
#include <stdio.h>

int main(void) {
    char s[] = "texto";
    char *c = s;

    for (int i = 0; i < 5; i++) {
        printf("%c", *(c + i));
    }
    return 0;
}

Faltou colocar parênteses para indicar que o valor deve ser somado ao endereço e não ao conteúdo do endereço.

No caso você estava fazendo:

't' + 0 = 't'

't' + 1 = 'u'

't' + 2 = 'v'

't' + 3 = 'w'

't' + 4 = 'x'

 

E um array já é um ponteiro para o primeiro elemento, então não é necessário fazer o casting de s para char*.

 

Você poderia substituir

printf("%c", *(c + i));

por

printf("%c", c[i]);

 

Postado
  Em 31/10/2022 às 02:59, XPointersX disse:

Porque quando eu passo "*c + i" dentro do printf ele deveria andar um byte e printar a segunda string no array.

Expandir  

 

Pois é. Só que não deveria

 

  Em 31/10/2022 às 02:59, XPointersX disse:

Usando "puts(c)" ele printa normal a palavra "texto"

Expandir  

 

Sim, porque assim é.

 

E porque afinal?

 

O programa está certo, o compilador está certo. O que está errado se quer mostrar a string é que

 

	printf("%c", *c + i);

 

devia ser

 

	printf("%c", *(c + i));

 

Assim estaria bem:

 

#include <stdio.h>

int main(void)
{
    char  s[] = "texto";
    char* c   = (char*)&s;

    for (int i = 0; i < 5; i++) { printf("%c", *(c + i)); }

    return 0;
}

 

mas dever preferir SEMPRE

 

#include <stdio.h>
int main(void)
{
    const char s[] = "texto";
    const char* c   = s;

    for (int i = 0; i < 5; i++) printf("%c", *(c + i));
    printf("\n");

    puts(s), puts(c); // exemplo

    printf("\n\t *s vale %d em decimal (%c)\n", *s, *s); // exemplo
    return 0;
}

 

porque a string é constante e assim o ponteiro também deve ser declarado como tal. Porque?

  • Nem todos os seus programas vão ter 5 linhas. E se resolver mudar algo na string --- de propósito ou por engano --- se declarar assim como const o compilador vai te avisar e não um telefonema no meio da noite ou um ponto a menos na nota com uma observação.
  • não use chaves a toa onde não precisa
  • mude de linha ao final da mensagem. É melhor do que deixar pra depois e colocar uma outra linha abaixo no programa que mostra outra coisa e sair tudo grudado e aí ter que voltar e mudar o que já devia ter feito.


Porque puts() funciona

 

puts() é como o loop que tentou escrever, só que pega o endereço inicial e põe na tela tudo o que tiver até achar um zero. Claro que ao declarar
 

        char s[] = "texto";

 

o zero está garantido depois do  'o'.

 

puts() funciona tanto para s e c 

 

    puts(s), puts(c);

 

porque são dois ponteiros para o mesmo lugar. Note que puts() mostra uma string por linha.

 

E porque "tuvwx"? 

 

Ao declarar 

 

    const char s[] = "texto";
    const char* c   = s;

 

s passa a apontar para uma área de memória com 6 bytes e lá estará a string com o zero no fim. É C afinal.

 

E c é um ponteiro e vai apontar para o mesmo endereço que s. 

 

*s e *c então são, claro, char, o "t". 
 

image.png.330ac2b2dc9297b1a1aa8dcd08f685dc.png


Quando você escreve 

 

    for (int i = 0; i < 5; i++) printf("%c", *(c + i));

 

Vai ver t, 116 na tabela, e depois 117, 118, 119, 120 😉 porque está somando ao valor de *c e não mostrando o endereço em 'c + i'

 

Veja os valores acima num trecho da tabela ASCII.

 

 

 

 

 

Postado

@XPointersX Sim, está errado. Leia o que eu expliquei. Tem mais exemplos e uma descrição do problema

  Em 31/10/2022 às 10:34, .if disse:

Algo como s= o endereço do conteúdo do endereço ? .. aff

Expandir  

 

Sim, mas nem precisava disso tudo. s já é implicitamente char*. Veja o que eu disse no tópico #5

 

    char  s[] = "texto";
    char* c   = (char*)&s;

 

s é char[6], mas em C todo vetor é isso, base e deslocamento. Um endereço de início e o tamanho.

 

Então pode escrever 

 

    const char  s[] = "texto";
    const char* c   = s;

 

E c é um ponteiro pra char e aponta para o mesmo lugar que s. E lá estão 6 bytes com o conteúdo declarado. 

Postado

@arfneto  Muito obrigado pela resposta, mas eu tenho outra pergunta. Se quando eu chamo um ponteiro de um vetor eu estou chamando o valor do endereço do vetor certo? Então eu estou chamando um endereço da stack? porque o vetor não foi alocado dinamicamente.

Postado

@XPointersX

  Em 31/10/2022 às 15:32, XPointersX disse:

Se quando eu chamo um ponteiro de um vetor

Expandir  

 

Não entendo o que seria "chamar um ponteiro de um vetor". Talvez pudesse postar outra pergunta já que é outra mesmo 😄 

 

Um ponteiro aponta para um endereço. Só isso. Tanto faz se está ou não no stack, se é válido ou inventado (isso até você tentar usar).

 

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Mostrar mais  

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

Mostrar mais  
×
×
  • Criar novo...