Change pointer address in a function

Asked

Viewed 592 times

1

I’m having trouble changing the address of a pointer within a function. I declare the pointer within the function, then pass it by parameter to another function. This other function should cause the pointer to point to another address. The problem is that once this function ends and returns to the function that called it, the pointer does not undergo any changes.

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

#define tam_max_bucket 2

int dir_prof=0;

typedef struct Buck{
 int profundidade;
 int contador;
 int chaves[tam_max_bucket];
}bucket;

typedef struct dir{
 struct Buck *bucket_ref;
}dir_cell;

dir_cell *diretorio;

int make_address(int key, int profundidade){
 int retVal, mask, hashVal, lowBit;
 retVal = 0;
 mask = 1;
 hashVal = key;
 int j;
 for(j=0; j<profundidade; j++){
    retVal = retVal << 1;
    lowBit = hashVal & mask;
    retVal = retVal | lowBit;
    hashVal = hashVal >> 1;
 }
return retVal;
}

int op_find(int key, bucket *found_bucket){
  int address = make_address(key, dir_prof);
  found_bucket = diretorio[address].bucket_ref;
  printf("\n%d\n", found_bucket->profundidade);
  printf("\n%d\n", diretorio[address].bucket_ref->contador);
  printf("\n%d\n", found_bucket->contador);
  int i;
  for(i=0; i<found_bucket->contador; i++){
      if(key == found_bucket->chaves[i])
        return 1;
  }
  return -1;
}

int op_add(int key){
  bucket *found_bucket = (bucket *) malloc(sizeof(bucket));
  printf("\nCont - %d\n", found_bucket->contador); //Imprime o valor do contador assim que found_bucket é alocada
  if(op_find(key, found_bucket) == 1){
    return -1;
  }
  printf("\nNovo valor%d\n", found_bucket->contador); //Imprime o valor de contador de found_bucket após a chamada da função. O valor não se altera, continua o mesmo
  return 1;
  }

void main(){
  diretorio =(dir_cell *) malloc(1*sizeof(dir_cell));
  diretorio[0].bucket_ref =(bucket *) malloc(sizeof(bucket));
  diretorio[0].bucket_ref->profundidade = 0;
  diretorio[0].bucket_ref->contador = 0;
  FILE *chaves;
  chaves = fopen("chaves.txt", "r+");
  if(chaves!=NULL){
      int chave;
      while((fscanf(chaves, "%d\n", &chave))!=EOF){
           printf("%d", chave);
           op_add(chave);
      }
   }
}
  • This code is confusing and done in a way that is far from ideal, so even if you fix this problem, it will still be far from a proper code. This is perhaps just the symptom and only a reformulation would solve everything. The code has a very inconsistent style. Where the problem occurs?

1 answer

2


The problem is that as soon as this function ends and returns to that called, the pointer undergoes no change

True because the value of the pointer has been copied to the other function, in the function op_add who calls the op_find:

int op_add(int key){
  bucket *found_bucket = (bucket *) malloc(sizeof(bucket));
  ...
  if(op_find(key, found_bucket) == 1){

In the expectation that the function op_find change its value:

int op_find(int key, bucket *found_bucket){
  ...
  found_bucket = diretorio[address].bucket_ref;

But this received a copy of the pointer, so it does not alter the original.

The solution to this problem is to pass the address of the pointer, ie a pointer to a pointer, like this:

int op_find(int key, bucket **found_bucket){ //alterada
  int address = make_address(key, dir_prof);
  *found_bucket = diretorio[address].bucket_ref; //atribuição com base no ponteiro para ponteiro
  printf("\n%d\n", (*found_bucket)->profundidade); //alterada
  printf("\n%d\n", diretorio[address].bucket_ref->contador);
  printf("\n%d\n", (*found_bucket)->contador); //alterada
  int i;
  for(i=0; i<(*found_bucket)->contador; i++){ //alterada
      if(key == (*found_bucket)->chaves[i]) //alterada
        return 1;
  }
  return -1;
}

Moreover always within this last function op_add change the pointer, with:

*found_bucket = diretorio[address].bucket_ref; //modifica o ponteiro

Here we have a memory leak because it had been allocated a Bucket in the previous function, in:

bucket *found_bucket = (bucket *) malloc(sizeof(bucket));

Who has not been released, so it is necessary to do free of the previous pointer before changing, or creating only the pointer without allocating memory.

Finally we can not forget that C does not initialize the memory, so accessing a structure that was allocated without assigning initial values will give random values, as is visible here:

bucket *found_bucket = (bucket *) malloc(sizeof(bucket));
printf("\nCont - %d\n", found_bucket->contador); //não é possível garantir o valor aqui, pois não foi inicializado

If the reason for changing the pointers is not very clear:

Additional reading on why to be pointer to pointer instead of normal pointer

Browser other questions tagged

You are not signed in. Login or sign up in order to post.