Passing pointers between functions
Hi,
I have been having a big problem passing pointers between functions and really need some help!
My program consists of a main function which calls other functions I've defined in a header file.
When the program runs, main calls a function to set up an array of struct pointers. Each element in the array is assigned a particular struct (hash table). If there is a collision (more than one struct is assigned to a particular element of the array), a linked list is constructed, where the first struct points to the next in the list, and so on. When the array is finished, it looks something like this (cut down example):
ARRAY
0 ----> struct ----> struct
1 ----> struct
2 ----> struct ----> struct ----> struct
3 ----> struct ----> struct
4 ----> struct ----> struct ----> struct
In main, I have initialised a structure (p_car_data) which contains a pointer of type struct pointer (i.e. it's a pointer to a pointer of type struct), called mp_car_table.
Main passes this structure to the first function, and when the array is complete, as above, it makes the pointer point at the array:
PHP Code:
p_car_data->mp_car_table = car_hash_table;
when the function exits, main is able to access the elements in the array, any any structs pointed to in linked lists as shown above.
PHP Code:
p_car_data->mp_car_table[3]->member
The problem I am having occurs when main passes this structure to other functions, hoping to access the array - all the struct pointers are lost!
I'm not sure why it's doing this, maybe I've made some mistake with pointers...
Can anyone help?
Thanks in advance
Paul
P.S. I have to stick with this structure (passing a structure containing the array pointer to the function, etc), as this is one part of a much larger program, and it's too late to turn back and change things...
Below (and also attached) is a small program which simulates the problem (the real program is too big to post here):
The example uses structs which represent cars, with make, model and value as the members.
PHP Code:
/*
// Main - calls the functions in doHash.h
//
// Passes a pointer to a struct to functions (p_car_data)
// p_car_data contains a pointer to the array created in initialise
// The array can be accessed in main (after initialise finishes),
// but not when passed from main to subsequent functions (print_cars)
//
*/
#include "stdafx.h"
#include "string.h"
#include "stdlib.h"
#include "doHash.h"
int main(void) {
/* Initialise the struct containing the array pointer */
data_return_t *p_car_data;
p_car_data = (data_return_t *)calloc(1, sizeof(data_return_t));
if (!p_car_data) {
fprintf(stderr, "Memory allocation error!\n");
exit(0);
}
/* Set up the array, pass the struct pointer to initialise function */
initialise(p_car_data);
/* Array pointer in struct working fine here */
fprintf(stderr, "\n\nFirst car: %s", p_car_data->mp_car_table[0]->mp_make);
/* Pass the same struct pointer to another function - all pointers to structs in p_car_data->mp_car_table (array) are lost! */
print_cars(p_car_data);
return 0;
}
/*
// Header file containing functions - doHash.h
//
*/
typedef struct car {
unsigned int value;
char *mp_make;
char *mp_model;
struct car *mp_next;
} car_t;
typedef struct data_tables {
struct car **mp_car_table;
int total_value;
} data_return_t;
void add_new_car(car_t **car_hash_table, char *s_make, char *s_model, unsigned int value, unsigned int element);
void print_cars(data_return_t *car_data);
int initialise(data_return_t *p_car_data) {
unsigned int element;
int i;
int a;
int value;
int total_value = 0;
char s_make[10];
char s_model[10];
car_t *car_hash_table[10] = {NULL};
/* Get the car make and model */
for (i = 0; i < 100; i++) {
a = i % 5;
if (a == 0) {
strncpy(s_make, "Ford", 4);
s_make[4] = '\0';
strncpy(s_model, "Escort", 6);
s_model[6] = '\0';
value = 3000;
}
if (a == 1) {
strncpy(s_make, "Vauxhall", 8);
s_make[8] = '\0';
strncpy(s_model, "Astra", 5);
s_model[5] = '\0';
value = 4500;
}
if (a == 2) {
strncpy(s_make, "VW", 2);
s_make[2] = '\0';
strncpy(s_model, "Beetle", 6);
s_model[6] = '\0';
value = 3000;
}
if (a == 3) {
strncpy(s_make, "Jaguar", 6);
s_make[6] = '\0';
strncpy(s_model, "XK8", 3);
s_model[3] = '\0';
value = 30000;
}
if (a == 4) {
strncpy(s_make, "Lotus", 5);
s_make[5] = '\0';
strncpy(s_model, "Esprit", 6);
s_model[6] = '\0';
value = 25000;
}
/* Calculate element in array to use - arbitrary value between 0 and 9 */
element = rand() % 10;
/* Add car to array */
add_new_car(car_hash_table, s_make, s_model, value, element);
total_value = total_value + value;
}
/* Set pointer to cars array in the data struct */
p_car_data->mp_car_table = car_hash_table;
p_car_data->total_value = total_value;
/* Print out listing of all cars */
print_cars(p_car_data);
return 0;
}
void add_new_car(car_t **car_hash_table, char *s_make, char *s_model, unsigned int value, unsigned int element) {
/* Add a new car (struct) to the hash table */
car_t *p_tmp_car;
car_t *p_new_car;
p_new_car = (car_t *)calloc(1, sizeof(car_t));
if (!p_new_car) {
/* CRITICAL ERROR: calloc failed */
exit(0);
}
p_new_car->mp_make = (char *)calloc(10, sizeof(char));
if (!p_new_car->mp_make) {
/* CRITICAL ERROR: calloc failed */
exit(0);
}
strncpy(p_new_car->mp_make, s_make, 10);
p_new_car->mp_model = (char *)calloc(10, sizeof(char));
if (!p_new_car->mp_model) {
/* CRITICAL ERROR: calloc failed */
exit(0);
}
strncpy(p_new_car->mp_model, s_model, 10);
p_new_car->value = value;
/* Add new car to array */
/* If collision, make last struct in list from that element point to new struct */
if (car_hash_table[element] == NULL) {
car_hash_table[element] = p_new_car;
}
else {
p_tmp_car = car_hash_table[element];
while(p_tmp_car->mp_next != NULL) {
p_tmp_car = p_tmp_car->mp_next;
}
p_tmp_car->mp_next = p_new_car;
}
}
void print_cars(data_return_t *car_data) {
/* Print all structs linking to the hash table */
unsigned int i;
car_t *p_tmp_car;
fprintf(stderr, "\nTotal value of cars is: %d ", car_data->total_value);
for(i = 0; i < 10; i++) {
p_tmp_car = car_data->mp_car_table[i];
if (p_tmp_car) {
while(1) {
fprintf(stderr, "\nElement: %d Make: %s, Model: %s", i, p_tmp_car->mp_make, p_tmp_car->mp_model);
/* If there is another car in the list, print it */
if (p_tmp_car->mp_next) {
p_tmp_car = p_tmp_car->mp_next;
}
else {
break;
}
}
}
}
fprintf(stderr, "\n\n");
}