Thread: Passing pointers between functions

  1. #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");


  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > 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.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #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

  4. #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.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > 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.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Jan 2004
    Posts
    6

    Thumbs up

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

    Paul

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Passing Pointers or References?
    By leeor_net in forum C++ Programming
    Replies: 24
    Last Post: 02-04-2009, 02:29 PM
  2. passing pointers in nested functions
    By tabstop in forum C Programming
    Replies: 6
    Last Post: 12-04-2008, 03:49 AM
  3. Passing lists to functions
    By Griever in forum C Programming
    Replies: 23
    Last Post: 11-14-2008, 05:26 PM
  4. Passing Pointers to Functions question..
    By transgalactic2 in forum C Programming
    Replies: 7
    Last Post: 10-18-2008, 03:51 PM
  5. Replies: 6
    Last Post: 05-06-2003, 03:08 PM