anil kumar
anil kumar

Reputation: 55

difference between structure pointers in c

Given the following structure:

struct node
{
    int data;
    struct node *next;
};

What is difference between following two functions:

void traverse(struct node *q);

and

void traverse(struct node **q);

How they are used?

Upvotes: 1

Views: 2258

Answers (4)

WhozCraig
WhozCraig

Reputation: 66194

One takes a pointer-to-node:

void traverse(struct node *q);

The other a pointer-to-pointer-to-node (note the name change of the function).

void insert(struct node **q);

The former is used when you need to access what is pointed-to. The latter is used when you need access to what is pointed-with I.e. you may need to modify the actual pointer variable from the caller-side as a potentially in and out parameter.

A good example of the former is a enumeration that is walking your linked list. You're not modifying the list head, you just need a pointer to the beginning node.

A good example of the latter is when you are pushing a node into a stack, when the list head pointer itself will be changed before finishing the function.

Like all things in C (arrays not withstanding) if you want to modify something as an output parameter you need to declare the parameter as a formal pointer-type and pass the address of the thing you're modifying. In the latter case (which I think is the one causing confusion), the thing we need to modify is a pointer variable itself, and thus it must be declared as a pointer-to-pointer and the address of a pointer is then passed in.

Examples speak loudly, so take a look:

#include <stdio.h>
#include <stdlib.h>

struct node
{
    int data;
    struct node *next;
};

void traverse(struct node* p)
{
    while (p)
    {
        printf("%d\n", p->data);
        p = p->next; // note. modifies only our local variable p.
                     // caller side uneffected.
    }
}

void insert(struct node **pp, int data)
{
    struct node *p = malloc(sizeof(*p));
    p->data = data;
    p->next = *pp;
    *pp = p; // note: save new list head here.
}

int main(int argc, char *argv[])
{
    struct node *head = NULL;
    insert(&head, 1);
    printf("head = %p\n", head);
    insert(&head, 2);
    printf("head = %p\n", head);
    insert(&head, 3);
    printf("head = %p\n", head);
    traverse(head);

    // yes, I know its leaking memory. that isn't the subject of this question.
    return 0;
}

Output

head = 0x1001000e0
head = 0x100103b40
head = 0x100103b50
3
2
1

Upvotes: 5

lulyon
lulyon

Reputation: 7225

This is similar to the difference between passing by value and passing by reference.

Here passing by struct node *q can modify the content that q point to and make effect to the content that the input pointer pointed to, but not the pointer itself. So It is similar to passing by value in which and q is a value of type struct node *

While passing by struct node **q could changed everything including the value and the address that the input pointer(maybe struct node *p; and pass &p), and resulted to p.

Upvotes: 0

xaxxon
xaxxon

Reputation: 19761

The first is a single pointer. It can modify data and next, but not what the parameter passed into the function points to. This is normally used when the space is already allocated for the structure.

q->data = 4; /* works */
q = malloc(sizeof(struct node)); /* new memory CANNOT be seen outside the function */

The second is a double pointer, so you can not only modify the fields data and next, but you can also malloc space for it and have the new space be seen outside the function.

(*q)->data = 4; /* works */
*q = malloc(sizeof(struct node)); /* new memory CAN be seen outside the function */

Upvotes: 2

John3136
John3136

Reputation: 29265

struct node *q says variable q is a pointer to a node.

struct node **q says variable q is a pointer to a pointer to a node.

struct node theNode;
struct node *p1 = &theNode;
struct node **p2 = &p1;

Upvotes: 1

Related Questions