C Board  

Go Back   C Board > General Programming Boards > C Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 01-09-2004, 04:39 AM   #1
Registered User
 
Join Date: Jan 2004
Posts: 6
Unhappy 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(1sizeof(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_tablechar *s_makechar *s_modelunsigned int valueunsigned 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 (0100i++) {

      
5;

      if (
== 0) {
         
strncpy(s_make"Ford"4);
         
s_make[4] = '\0';
         
strncpy(s_model"Escort"6);
         
s_model[6] = '\0';
         
value 3000;
      }

      if (
== 1) {
         
strncpy(s_make"Vauxhall"8);
         
s_make[8] = '\0';
         
strncpy(s_model"Astra"5);
         
s_model[5] = '\0';
         
value 4500;
      }

      if (
== 2) {
         
strncpy(s_make"VW"2);
         
s_make[2] = '\0';
         
strncpy(s_model"Beetle"6);
         
s_model[6] = '\0';
         
value 3000;
      }

      if (
== 3) {
         
strncpy(s_make"Jaguar"6);
         
s_make[6] = '\0';
         
strncpy(s_model"XK8"3);
         
s_model[3] = '\0';
         
value 30000;
      }

      if (
== 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_tables_makes_modelvalueelement);
      
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_tablechar *s_makechar *s_modelunsigned int valueunsigned 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(1sizeof(car_t));
   if (!
p_new_car) {
      
/* CRITICAL ERROR: calloc failed */
      
exit(0);
   }

   
p_new_car->mp_make = (char *)calloc(10sizeof(char));
   if (!
p_new_car->mp_make) {
      
/* CRITICAL ERROR: calloc failed */
      
exit(0);
   }
   
strncpy(p_new_car->mp_makes_make10);

   
p_new_car->mp_model = (char *)calloc(10sizeof(char));
   if (!
p_new_car->mp_model) {
      
/* CRITICAL ERROR: calloc failed */
      
exit(0);
   }
   
strncpy(p_new_car->mp_models_model10);

   
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(
010i++) {
      
p_tmp_car car_data->mp_car_table[i];
      if (
p_tmp_car) {
         while(
1) {
            
fprintf(stderr"\nElement: %d Make: %s, Model: %s"ip_tmp_car->mp_makep_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");

heygirls_uk is offline   Reply With Quote
Old 01-09-2004, 07:46 AM   #2
and the hat of Jobseeking
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,661
> p_car_data->mp_car_table = car_hash_table;
This is the real problem - car_hash_table is a local array, which means it no longer exists when the function exits.

Code:
static car_t *car_hash_table[10] = {NULL};
is a quick hack fix, but you should really allocate this dynamically.

Code:
         strncpy(s_make, "Ford", 4);
         s_make[4] = '';
An empty pair of single quotes is a syntax error.
Besides, in these cases, you may as well just use a regular strcpy()

> p_car_data = (data_return_t *)calloc(1, sizeof(data_return_t));
Casting the result of malloc generally a bad idea in C - perhaps you're using a C++ compiler and don't know it.
See the FAQ

You also don't include stdio.h, for prototyping printf()

One more point, please use the code tag, not the php tag when posting code.
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.

Salem is offline   Reply With Quote
Old 01-09-2004, 02:40 PM   #3
Registered User
 
Join Date: Jan 2004
Posts: 6
Many thanks for your help - I've got it all working now.

As regards the following statement:

s_make[4] = ' ';

This was supposed to read:

s_make[4] = '\0'; /* null character */

For some reason all NULL characters were removed from my post.

I usually assign strings using strncpy to prevent buffer overflow... I always thought that if you fill the string up including the last element, there won't be room for the NULL character, so the string will terminate whenever the first NULL character is reached in memory.

Do I need to insert the NULL character when using calloc to allocate a string dynamically, or is the NULL character inserted automatically? And can it be overwritten using strcpy, or will strcpy always stop when it reaches the NULL?

Thanks again,

Paul
heygirls_uk is offline   Reply With Quote
Old 01-09-2004, 03:21 PM   #4
Deleted Account
 
Join Date: Jan 2004
Posts: 40
calloc zeros all the memory that is allocated, I believe so there is no need to null-terminate (unless you are shortening the string) as it has already been done for you.
Brian2 is offline   Reply With Quote
Old 01-09-2004, 03:50 PM   #5
and the hat of Jobseeking
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,661
> I usually assign strings using strncpy to prevent buffer overflow..
In which case, you should be doing
strncpy(s_make, "Ford", sizeof s_make);
s_make[sizeof s_make -1] = '\0';

> For some reason all NULL characters were removed from my post.
Yeah, you used php tags instead of code tags

> And can it be overwritten using strcpy, or will strcpy always stop when it reaches the NULL?
strcpy() doesn't care about whether you use calloc or malloc. All it cares about is havinf a nul character in the source string.
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.

Salem is offline   Reply With Quote
Old 01-09-2004, 06:58 PM   #6
Registered User
 
Join Date: Jan 2004
Posts: 6
Thumbs up

Thanks for clearing that up, it makes much more sense now

Paul
heygirls_uk is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Passing Pointers or References? leeor_net C++ Programming 24 02-04-2009 02:29 PM
passing pointers in nested functions MK27 C Programming 6 12-04-2008 03:18 AM
Passing lists to functions Griever C Programming 23 11-14-2008 05:26 PM
Passing Pointers to Functions question.. transgalactic2 C Programming 7 10-18-2008 03:51 PM
Passing variables to functions (was: Problem with functions) OmniMirror C Programming 6 05-06-2003 03:08 PM


All times are GMT -6. The time now is 02:28 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22