Thread: pointer probs. with structs.

  1. #1
    Registered User dinjas's Avatar
    Join Date
    Feb 2005
    Location
    Vancouver, Washington
    Posts
    40

    pointer probs. with structs.

    Hi, I'm having problems compiling the following simple code. I'm trying to see how this works on a small scale before I move the idea into this program I'm working on. Quzah kind of explained this to me the other day but it's not quite clicking for this exact application...

    Code:
     #include <stdio.h>
         
    struct node
    {
      int data;
      struct node* next;
    };
    
    void foo(struct node** n )
    {
      *n->data = 5;
    }
     
    int main( void )
    {
    
      struct node* root = NULL;
      root = malloc(sizeof(struct node));
      root->data=3;
      printf("root->data = %d", root->data);
      foo( &root );
      printf("root->data = %d", root->data);
      return 0;
    
    }
    My compiler is telling me that in my function foo, data is not a member of the struct. I'm sure this has to do with the dereferencing but it doesn't seem to matter how many *'s I put, 0, 1, or 2. I still get the message. I pass in a ptr to a ptr. as an address of a ptr. But to access the data, I use the ->data which is the same as using one * for dereferencing right? So, I need to use 1 more to change the value of the data? Also, the compiler doesn't like my malloc call in main. Says I'm making a pointer from an integer without a cast. I've used malloc like this before though, so ??? I'm I doin bad stuff?
    I need to be able to pass pointers to structs to functions and be able to modify elements in the structures and have the changes stay. Thanks
    dinjas
    straight off the heap

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Code:
    (*n)->data = 5;
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User dinjas's Avatar
    Join Date
    Feb 2005
    Location
    Vancouver, Washington
    Posts
    40
    ughhhh
    ( 1 hour
    ) 2 hour, 3 hour, 4 ...

    so any time you dereference something with the -> after it you need the parens? never would have thought of it..

    thanks!
    straight off the heap

  4. #4
    Registered User
    Join Date
    Sep 2001
    Posts
    4,912
    You'll find a precedence table useful for this type of thing. It'll help you see how an expression will be interpreted.

  5. #5
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    For your purpose here, changing the value of the struct member, you don't need to make the function accept a pointer to a pointer to struct node. A single pointer to type struct node would suffice. This would eliminate the need for passing the address of root to the foo function and the extra dereferencing and use of parenthesis steps within the foo function. You could have simply done this and achieved the same effect:

    Code:
    struct node
    {
      int data;
      struct node* next;
    };
    
    void foo(struct node* n )  // Single pointer
    {
       n->data = 5;  // No extra parenthesis and dereferencing needed here
    }
     
    int main( void )
    {
    
      struct node* root = NULL;
      root = malloc(sizeof(struct node));
      root->data=3;
      printf("root->data = %d", root->data);
      foo( root );  // No address of operator (&) needed
      printf("root->data = %d", root->data);
      return 0;
    
    }
    Now, if on the other hand you wished to change what root pointed to by passing it in as a parameter, then you would need to use a pointer to a pointer to struct node, i.e.:

    Code:
    struct node
    {
        int data;
        struct node* next;
    };
    
    void foo1(struct node* n )
    {
        n = (node*) malloc(sizeof(struct node));
        n->data = 3;
    }
    
    void foo2(struct node** n )
    {
        *n = (node*) malloc(sizeof(struct node));
        (*n)->data = 10;
    }
     
    int main( void )
    {
    
        struct node* root = NULL;
    
        foo1( root);
        if( root != NULL )
            printf("root->data = %d after foo1\n", root->data);
        else
            printf("root is still NULL after foo1\n");
    
        foo2( &root );
        if( root != NULL )
            printf("root->data = %d after foo2\n", root->data);
        else
            printf("root is still NULL after foo2\n");
    
        return 0;
    }
    Which outputs:
    Code:
    root is still NULL after foo1
    root->data = 10 after foo2
    Or, foo2 could have been done as a void function returning a pointer to struct node and having the same effect:
    Code:
    struct node* foo2()
    {
        struct node *n = malloc(sizeof(struct node));
        n->data = 10;
        return n;
    }
    Which would be called like so:
    Code:
    struct node *root = NULL;
    ...
    root = foo2();
    if( root != NULL )
        printf("root->data = %d after foo2\n", root->data);
    else
        printf("root is still NULL after foo2\n");
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  6. #6
    Registered User dinjas's Avatar
    Join Date
    Feb 2005
    Location
    Vancouver, Washington
    Posts
    40
    Thanks for the clarification. Is one method better practice than the other?
    i.e.

    Code:
    foo2(&root);
    vs.

    Code:
    root=foo2();
    Does it just depend on the implementation?
    (trying not to develop too many bad habits)

    thanks again.
    straight off the heap

  7. #7
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    If you need to pass a value and then modify it inside the function, having the change persist outside of the function, a pointer is the way to go. If you don't need to pass anything, but are simply getting a value from a function and assigning it to something outside the function, then return value assignment works well.

    Really it's a matter of preference. But the above is a good general rule of thumb.

    Quzah.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. sorting the matrix question..
    By transgalactic2 in forum C Programming
    Replies: 47
    Last Post: 12-22-2008, 03:17 PM
  2. pointer to array of structs
    By Luken8r in forum C Programming
    Replies: 4
    Last Post: 01-02-2008, 11:20 AM
  3. towers of hanoi problem
    By aik_21 in forum C Programming
    Replies: 1
    Last Post: 10-02-2004, 01:34 PM
  4. Replies: 41
    Last Post: 07-04-2004, 03:23 PM
  5. Quick question about SIGSEGV
    By Cikotic in forum C Programming
    Replies: 30
    Last Post: 07-01-2004, 07:48 PM