Dúvida com ponteiros e estruturas em C

1. Dúvida com ponteiros e estruturas em C

Paulo Pimenta
paulopimenta6

(usa Debian)

Enviado em 30/03/2021 - 15:21h

Olá pessoal,

Estava estudando C e ao fazer um código que envolve estruturas e ponteiros tive um problema de retorno do valor de uma das variaveis da estrutura. Aparece sempre "segmentantion Fault" quando tento imprirmir na função "main" o valor de um inteiro que é atribuído a uma das variáveis da estrutura. Abaixo segue o código:


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

struct Lista *insere_final(struct Lista *n, int x); //prototipo da funcao

struct Lista{
    int valor;
    struct Lista *proximo; //ponteiro para a proxima entrada da lista
                           //uso de recursividade. Uma struct dentro de outra
};

int main(){
    struct Lista *inicio;
    insere_final(inicio, 10);

    printf("O valor fora da funcao de inicio->valor e: %d \n", inicio->valor);

    return 0;
}

struct Lista *insere_final(struct Lista *n, int x){
struct Lista *novo=(struct Lista *)malloc(sizeof(struct Lista)); //alocou memoria dinamicamente para a lista
novo->valor=x;
if(n==NULL){//lista nao esta vazia
    printf("n esta vazio! \n");
    novo->proximo=NULL;
    printf("1 - O valor dentro da funcao de novo->inicio: %d \n", novo->valor);
    return novo; //novo no sera o inicio da lista
}
else{//lista nao esta vazia-vamos ao final para inserir o no
    struct Lista *temp=n; //criando referencia ao primeiro no
    while(temp->proximo!=NULL){//e preciso ir ao ultimo no
        temp=temp->proximo;
    }
    novo->proximo=NULL;
    temp->proximo=novo;//o ultimo no apontara para o novo no
    printf("Entrou em else e esta verificando temp \n");
    return n;
}

}
 


Desde já agradeço a todos que possam ajudar!


  


2. Re: Dúvida com ponteiros e estruturas em C

3. Re: Dúvida com ponteiros e estruturas em C

berghetti
berghetti

(usa Debian)

Enviado em 30/03/2021 - 18:28h

fiz alguma ajustes (comentados)
mas principalmente alterei o primeiro argumento da função 'insere_final' de ponteiro para ponteiro para ponteiro.

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

struct Lista *insere_final(struct Lista **n, int x); //prototipo da funcao

struct Lista{
  int valor;
  struct Lista *proximo; //ponteiro para a proxima entrada da lista
                         //uso de recursividade. Uma struct dentro de outra
};

// deve ser int main(void) ou da forma que esta, numca 'int main ()'
int main(int argc, char *argv[]){
  struct Lista *inicio = NULL; //ponteiro inicializado;
  struct Lista *temp;
  int i = 0;

  // preenche a lista
  insere_final( &inicio, 10 );
  insere_final( &inicio, 20 );
  insere_final( &inicio, 30 );
  insere_final( &inicio, 40 );

  // percorre toda a lista
  temp = inicio;
  while( temp )
  {
    printf("elemento %d valor %d\n", ++i, temp->valor);
    temp = temp->proximo;
  }

  return 0;
}

// alterado o n para ponteiro para ponteiro, assim podemos alterar o conteudo 
// de da variavel 'inicio'
struct Lista *insere_final(struct Lista **n, int x){
  struct Lista *novo = malloc(sizeof(struct Lista)); // cast desnecessario, o retorno de malloc é 'void *' que é automaticamente
                                                     // convertido para qualquer tipo

  // verificação de malloc
  if (!novo)
    return NULL;

  novo->valor = x;

  if( *n == NULL ){ //lista esta vazia
    printf("ESTA vazio! \n");
    novo->proximo = NULL;
    printf("1 - O valor dentro da funcao de novo->inicio: %d \n", novo->valor);
    *n = novo;    // salva referência de 'novo'
  }
  else{ //lista nao esta vazia-vamos ao final para inserir o no
    struct Lista *temp = *n; //criando referencia ao primeiro no

    while(temp->proximo != NULL){ //e preciso ir ao ultimo no
      temp = temp->proximo;
    }

    novo->proximo = NULL;
    temp->proximo = novo; //o ultimo no apontara para o novo no
    printf("Entrou em else e esta verificando temp \n");
  }

  return novo;

} 


para entender o motivo disso,
esse código pode ser útil (compile e rode)

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

void
modifica_conteudo_ponteiro(int *p, int v)
{
  *p = v;
}

void
modifica_conteudo_ponteiro_ponteiro(int **p)
{
  // *p = (int *) 0xFFFFFFFFFFFF;
  // malloc vai retornar um endereço
  *p = malloc(sizeof(int));
}

int main(void)
{
  int x = 10;

  // p == ponteiro
  // pp == ponteiro para ponteiro
  int *p;
  int **pp;

  p = &x;
  pp = &p;

  printf( "%d \t\t- conteúdo de x\n", x );
  printf( "%p \t- endereço de x\n\n", &x );

  printf( "%p \t- endereço de p\n", &p );
  printf( "%p \t- conteúdo de p (o mesmo que endereço de x)\n", p );
  printf( "%d \t\t- conteúdo presente no endereço apontado por p (o mesmo que conteúdo de x)\n\n", *p );

  printf( "%p \t- endereço de pp (ponteiro para ponteiro para ponteiro, numca usei)\n", &pp );
  printf( "%p \t- conteúdo de pp (o mesmo que endereço de p)\n", pp );
  printf( "%p \t- conteúdo presente no endereço apontado por pp (o mesmo que endereço de x)\n", *pp );
  printf( "%d \t\t- valor presente no endereço apontado pelo endereço apontado por pp (o mesmo que conteúdo de x)\n\n\n\n", *(*pp) );

 /*
    endereços fictícios
    0xFFFA    endereço da variável x
    10        conteúdo da variável x

    0xFFFB    endereço da variável p
    0xFFFA    conteúdo da variável p  ( endereço da variavél x )
    10        conteúdo que possui no endereço armazenado por p ( conteúdo da variável x )

    0xFFFC    endereço da variável pp
    0xFFFB    conteúdo da variável pp ( endereço da variavél p )
    0xFFFA    conteúdo que possui no endereço armazenado por pp (o endereço da variável x )
    10        valor presente no endereço apontado pelo endereço apontado por pp

    logo se eu tenho
    int x; (uma variavel do tipo x)

    e quiser modificar o conteúdo de x em uma função, deve passar o endereço
    de x para que a função acessa essa posição de memoria e escreva um valor lá,
    então fica
  */
  modifica_conteudo_ponteiro(&x, 25);
  printf("%d \t\t- o valor de x foi modificado\n\n", x);

  /*
    mas se eu tenho
    int *p; (um ponteiro que armazena um endereço que contem um dado do tipo inteiro)

    e quiser modificar o conteudo de p, atenção eu disse o conteúdo de p
    e não o valor apontado pelo conteúdo de p,
    devemos da mesma forma passar o endereço de p, como p ja é um ponteiro e
    temos que pessar seu endereço para modificar seu conteudo, logo temos que passar
    um ponteiro para ponteiro
  */
  modifica_conteudo_ponteiro_ponteiro(&p);
  printf("%p \t- novo conteudo em p\n\n", p);

  /*
    se quiser modificar o valor presente na memória apontada por p,
    passamos o endereço dessa memória para uma função, ou seja, passamos
    o conteúdo de p.
  */

  modifica_conteudo_ponteiro(p, 76);
  printf("%d \t\t- novo valor presente no endereço de memória apontada por p\n\n", *p);

  /*
    se eu tenho
    int **pp (um ponteiro que armazena o endereço de um ponteiro que por sua vez aponta para a posição de memória que tem um tipo int)
    e quiser modificar seu conteudo,
    ou seja,
    se pp tem o valor 0xFFFF, e eu quiser colocar o valor 0xAAAA
    preciso passar seu endereço (&pp)
    mas esse nivel de apontamento não é muito utilizado,

    é mais comum precisarmos alterar o valor que o endereço de pp aponta,
    do que o contéudo de pp propriamente,
    logo passamos esse endereço de memória para modificar,
    assim
  */

  pp = &p;
  printf("%p \t- novo conteudo de pp\n\n", pp);
  printf("%p \t- novo conteúdo presente no endereço apontado por pp\n\n", *pp);
  printf("%d \t\t- novo valor presente no endereço apontado pelo endereço apontado por pp\n\n", *(*pp));


  return 0;
}
 







Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts