Thread: Passing stucts by reference, malloc

  1. #1
    Registered User
    Join Date
    Jul 2006
    Posts
    4

    Passing stucts by reference, malloc

    Alright, I'm relatively new to C but not to programming. What I'm trying to do is create a struct, pass it to another function that will allocate memory for it and fill it.

    Here's an example of what I'm doing, which creates exactly the same situation that I am dealing with

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct _dog {
    	char age;
    	char weight;
    } dog;
    
    void makenewdog(dog * dogtomake) {
    	dogtomake = (dog *) malloc(sizeof(dog));
    	dogtomake->age = 1;
    	dogtomake->weight = 5;
            /* this prints 5, which is correct */
    	printf("Ok, I made you a dog. It's %d pounds.\n", dogtomake->weight);
    }
    
    int main (int argc, const char * argv[]) {
    	dog doggie;
    	doggie.weight = 0; doggie.age = 0;
    	
    	makenewdog(&doggie);
    	
    	/* weight should now be 5, but it returns 0. doggie's pointer isn't changed to
    	   respect what it was given in makenewdog either */
    	printf("I have a dog now, %d pounds.\n", doggie.weight);
    	return 0;
    }
    Any pointers (no pun intended) in the right direction would be a great help, thanks!
    Last edited by toveling; 07-04-2006 at 12:32 AM.

  2. #2
    Awesomefaceradcore bivhitscar's Avatar
    Join Date
    Apr 2006
    Location
    Melbourne, Australia
    Posts
    210
    You probably need to create a pointer to the dog struct in order for it to work.

    Try changing to this:

    Code:
    int main (int argc, const char * argv[]) {
    	dog * doggie;
    	
    	makenewdog(doggie);
    	
    	printf("I have a dog now, %d pounds.\n", doggie -> weight);
    	return 0;
    }

    [EDIT]

    Oh, and don't cast malloc - http://faq.cprogramming.com/cgi-bin/...&id=1043284351
    Last edited by bivhitscar; 07-04-2006 at 12:43 AM.
    it's ironic considerate rarity patron of love higher knowledge engulfs me...

  3. #3
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    If you wish to allocate the memory in the called function, you will have to pass a pointer to a pointer as demonstrated:
    Code:
    void makenewdog(dog ** dogtomake) {
            dog* tempDog; /* Don't need to use a temp but provides cleaner code. */
    
    	tempDog = malloc(sizeof(dog));
    	tempDog->age = 1;
    	tempDog->weight = 5;
            /* this prints 5, which is correct */
    	printf("Ok, I made you a dog. It's %d pounds.\n", tempDog->weight);
    
            *dogtomake = tempDog; /* Store the value of tempDog in the pointer provided by the calling function. */
    }
    
    int main (int argc, const char * argv[]) {
    	dog * doggie; /* Do not use this until allocated in makenewdog. */
    
    	makenewdog(&doggie); /* Pass the address of a dog pointer. */
    	
    	/* weight should now be 5, but it returns 0. doggie's pointer isn't changed to
    	   respect what it was given in makenewdog either */
    	printf("I have a dog now, %d pounds.\n", doggie->weight);
    	return 0;
    }
    The other option is to return the dog pointer as the return value of the makenewdog function.

    I would say that is often not a good idea to allocate the structure in the called function. The calling function can be responsible for allocation (either using malloc or on the stack) and then pass it to a function to complete its data if required.

    EDIT: bivhitscar, remember that C always passes function arguments by value. In your example, the value passed to makenewdog is the uninitialised random value of the doggie variable.
    Last edited by anonytmouse; 07-04-2006 at 12:54 AM.

  4. #4
    Registered User
    Join Date
    Jul 2006
    Posts
    4
    [edit]
    I was replying to #2, now 3

    Thanks anonytmouse, that worked perfectly. I sort of had an idea that I would need to do something like that, but I've never worked with pointers to pointers before.

    Thanks for the assistance, you've been a great help!
    Last edited by toveling; 07-04-2006 at 01:02 AM.

  5. #5
    Awesomefaceradcore bivhitscar's Avatar
    Join Date
    Apr 2006
    Location
    Melbourne, Australia
    Posts
    210
    Ignore my solution, I was wrong. :P

    But you still shouldn't cast malloc.
    it's ironic considerate rarity patron of love higher knowledge engulfs me...

  6. #6
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Why pass an unitialized pointer in the first place? The makedog function should make your data structure available out of nothing. I would try returning a pointer from the constructor, like this:

    Code:
    struct dog {
        int age;
        int weight;
    };
    
    struct dog *makedog(int age_in, int weight_in) {
        struct dog *rex = malloc( sizeof(struct dog) );
        rex->age = age_in;
        rex->weight = weight_in;
        return rex;
    }
    
    void freedog(struct dog **me) {
        free(*me);
        *me = NULL;
    }
    The free function is probably a good idea too, to emulate a destructor. I passed a pointer to a pointer to avoid making a temporary, but dog seems small enough not to worry about it.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Try again bivhitscar

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct _dog {
    	char age;
    	char weight;
    } dog;
    
    dog *makenewdog() {
    	dog * dogtomake;
    	dogtomake = malloc(sizeof(*dog));
    	dogtomake->age = 1;
    	dogtomake->weight = 5;
            /* this prints 5, which is correct */
    	printf("Ok, I made you a dog. It's %d pounds.\n", dogtomake->weight);
    	return dogtomake;
    }
    
    int main (int argc, const char * argv[]) {
    	dog *doggie;
    	
    	doggie = makenewdog();
    	
    	/* weight should now be 5, but it returns 0. doggie's pointer isn't changed to
    	   respect what it was given in makenewdog either */
    	printf("I have a dog now, %d pounds.\n", doggie->weight);
    	return 0;
    }
    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.

  8. #8
    Awesomefaceradcore bivhitscar's Avatar
    Join Date
    Apr 2006
    Location
    Melbourne, Australia
    Posts
    210
    Thanks salem; my thought processes are still developing.
    it's ironic considerate rarity patron of love higher knowledge engulfs me...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Passing structure by reference or pointer?
    By 7force in forum C Programming
    Replies: 8
    Last Post: 12-13-2010, 06:49 PM
  2. In over my head
    By Shelnutt2 in forum C Programming
    Replies: 1
    Last Post: 07-08-2008, 06:54 PM
  3. Undefined Reference Compiling Error
    By AlakaAlaki in forum C++ Programming
    Replies: 1
    Last Post: 06-27-2008, 11:45 AM
  4. Question about OpenGL/Linux
    By Ideswa in forum Linux Programming
    Replies: 12
    Last Post: 09-10-2006, 05:56 AM
  5. GCC - Strange networking functions error.
    By maththeorylvr in forum Windows Programming
    Replies: 3
    Last Post: 04-05-2005, 12:00 AM