nick_name
nick_name

Reputation: 1373

C - Passing a Pointer to a Function and then Passing that Same Pointer Inside the Function to Another Function

Whew! Long title...here's some pseudo-code to explain that verbiage:

int main(){
int* ptr = function1(); //the data that ptr points to is correct here
function2(ptr);
}

int function2(int* ptr){
//the data that ptr points to is still correct
int i;
for(i=0;i<length;printf("%d\n", (*ptr)[i]), i++); //since ptr points to a contiguous block of memory
function3(ptr);
}

int function3(int* ptr){
//the data that ptr points to is INCORRECT!!!
}

Why would the data in function3 be incorrect?

Note: function1 performs a malloc() and returns the pointer to that memory.

ACTUAL CODE

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

//Structures
struct hash_table_data_
{
  int key, data;
  struct hash_table_data_ *next, *prev;
};

struct hash_table_
{
  int num_entries;
  struct hash_table_data_ **entries;
};

typedef struct hash_table_data_ hash_table_data;
typedef struct hash_table_ hash_table;

//Prototypes
hash_table *new_hash_table(int num_entries);
int hash_table_add(hash_table *ht, int key, int data);
int hash_table_loader(hash_table* ht);

//Main
int main()
{
  int num_entries = 8;//THIS MUST BE AUTOMATED

  hash_table* ht = new_hash_table(num_entries);
  hash_table_loader(ht);

  return 0;
}

//Function Definitions
hash_table *new_hash_table(int num_entries)
{
  hash_table* ht = (hash_table*) malloc(sizeof(hash_table));

  hash_table_data* array = malloc(num_entries * sizeof(hash_table_data));
  int i;
  for (i=0;i<num_entries;i++)
    {
      array[i].key = -1;
      array[i].data = -1;
      array[i].next = NULL;
      array[i].prev = NULL;
    }

  ht->entries = &array;
  ht->num_entries = num_entries;

  return ht;
}

int hash_table_add(hash_table *ht, int key, int data)
{
  //VERIFY THAT THE VALUE ISN'T ALREADY IN THE TABLE!!!!!!!!!!!
  int num_entries = ht->num_entries;
  hash_table_data* array = *(ht->entries); //array elements are the LL base
  int hash_val = key%num_entries;

  printf("adding an element now...\n");
  printf("current key: %d\n", array[hash_val].key);

  int i;
  for(i=0;i<num_entries;printf("%d\n", (*(ht->entries))[i].key),i++);//DATA IS INCORRECT!!!!

  if (array[hash_val].key == -1)//is this the base link?
    {
      printf("added a new base link!\n");
      array[hash_val].key = key;
      array[hash_val].data = data;
      array[hash_val].next = NULL;
      array[hash_val].prev = &(array[hash_val]);
    }
  else//since it's not the base link...do stuff
    {
      hash_table_data* new_link = malloc(sizeof(hash_table_data));
      new_link->key = key;//set the key value
      new_link->data = data;//set the data value
      if (array[hash_val].next == NULL)//we must have the second link
    {
      printf("added a new second link!\n");
      new_link->prev = &(array[hash_val]); //set the new link's previous to be the base link
      array[hash_val].next = new_link; //set the first link's next
    }
      else//we have the 3rd or greater link
    {
      printf("added a new 3rd or greater link!\n");
      hash_table_data next_link_val = *(array[hash_val].next);
      while (next_link_val.next != NULL)//follow the links until we reach the last link
        {
          next_link_val = *(next_link_val.next);//follow the current link to the next
        }
      //now that we've reached the last link, link it to the new_link
      next_link_val.next = new_link; //link the last link to the new link
      new_link->prev = &(next_link_val); //link the new link to the last link
    }
    }

  return 0;
}

int hash_table_loader(hash_table* ht)
{
  int i;
  for(i=0;i<(ht->num_entries);printf("%d\n", (*(ht->entries))[i].key),i++); //DATA IS STILL CORRECT HERE

  FILE *infile;
  infile = fopen("input.txt", "r");
  while(!feof(infile))
    {
      int key,data;
      fscanf(infile, "%d %d", &key, &data);
      hash_table_add(ht, key, data);
    }
  fclose(infile);
}

Note: Issue occurring the first time hash_table_add() is called.

Upvotes: 0

Views: 195

Answers (3)

Mahesh
Mahesh

Reputation: 34625

hash_table *new_hash_table(int num_entries)
{
    hash_table* ht = (hash_table*) malloc(sizeof(hash_table));

    hash_table_data* array = malloc(num_entries * sizeof(hash_table_data));

    // ....

    ht->entries = &array; // Problem

    // ...
    return ht;
} // Life time of array ends at this point.

You are taking the reference of the local variable array and assigning it to ht->entries which is no more valid once the function returns.

Upvotes: 0

Karl Knechtel
Karl Knechtel

Reputation: 61519

Your first problem is here:

ht->entries = &array;

You cause the structure to hold a hash_table_data** which points to the variable hash_table_data* array which is local to the function; then you exit the function and return a pointer to the structure. The structure still exists (it was allocated via malloc(), and the stuff that array points to still exists, but array itself does not. Accordingly, this pointer within the structure is now invalid.

As far as I can tell, there is no reason for you to be holding a pointer-to-pointer here. Just use hash_table_data* as the entries type, and copy array into that struct member. Pointers are values too.

Upvotes: 7

unkulunkulu
unkulunkulu

Reputation: 11912

I guess you iterate incorrectly

for(i=0;i<length;printf("%d\n", (*ptr)[i]), i++);

this is nonsense.

You should rewrite it as this:

for(i=0;i<length;i++)
    printf("%d\n", ptr[i]);

(*ptr)[i] is just wrong, it doesn't make sense if you think about it.

*ptr is the first element of the pointed-to array of ints. ptr[i] is thi ith one, this is what you need.

Please, read Section 6 carefully.

A couple of advises based on this question:

  1. Don't write overcomplicated code like this for statement with comma operator used, it just rarely needed and leads not only to confusion, but to mistakes (although no mistakes with it in this particular example)
  2. Look carefully for mistakes, don't blame everything on functions. If your code doesn't work, try finding the exact place which is wrong and prove it. In this example people who tested your code were right: functions are definitely not the cause of the error.

Upvotes: 0

Related Questions