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