Pointer to a pointer, how do I get values? - c

Lets say I have the following code,
typedef struct WordNode WordNode;
struct WordNode {
int freq; // The frequency of the the word.
char *word; // The word itself.
WordNode *next; // The next word node in the list.
};
struct WordSet {
int size; // The number of elements in the set.
WordNode *head; // The starting node in the set.
};
After this, I've got some functions that initialize these structs. To prevent too much code in this post, I'm going to avoid posting those functions here.
Now, lets say I have the following,
WordNode **p = wset->head; // can't change this line
Here, p is basically a pointer pointing to a pointer, correct?
And then, if I do this:
(*p) == NULL
This would return true if p is pointing to NULL, right?
Now, how would I get the word stored in wset->head?
Can I do this?
(*(*p))->word
And if I want p to point to the next WordNode, can I do this?
p = (*(*p))->next
I just want to know if all this is valid syntax so that I know I'm using pointers correctly.

Not really. (*(*p))->word is a total dereferenciation. So it would either be (*(*p)).word or (*p)->word.
You can imagine it that way, that the ->-Operator takes away one reference for you.
obj->field is the same as (*obj).field

Just for the sake of simplicity, whenever I have to deal with double pointer and I need the value I all the time go via an intermediate variable
e.g.
WordNode **ptr2ptr = wset->head;
WordNode *ptr = *ptr2Ptr;
WordNode value = *ptr;
or to get the head:
WordNode head = ptr->head;
Now I'm just answering the question which is, how to access the value of a pointer to pointer. You must be careful that your wset->head contains actually a pointer to pointer which is normally not the case in a linked list the way I understand you are trying to do. This is also not the way you have defined your head member...

Related

what does this struct node **p is doing?

I am learning data structure, and here is a thing that I am unable to understand...
int end(struct node** p, int data){
/*
This is another layer of indirection.
Why is the second construct necessary?
Well, if I want to modify something allocated outside of my function scope,
I need a pointer to its memory location.
*/
struct node* new = (struct node*)malloc(sizeof(struct node));
struct node* last = *p;
new->data = data;
new->next = NULL;
while(last->next !=NULL){
last = last ->next ;
}
last->next = new;
}
why we are using struct node **p?
can we use struct node *p in place of struct node **p?
the comment which I wrote here is the answer I found here, but still, I am unclear about this here is the full code...
please help me
thank you
Short answer: There is no need for a double-pointer in the posted code.
The normal reason for passing a double-pointer is that you want to be able to change the value of a variable in the callers scope.
Example:
struct node* head = NULL;
end(&head, 42);
// Here the value of head is not NULL any more
// It's value was change by the function end
// Now it points to the first (and only) element of the list
and your function should include a line like:
if (*p == NULL) {*p = new; return 0;}
However, your code doesn't !! Maybe that's really a bug in your code?
Since your code doesn't update *p there is no reason for passing a double-pointer.
BTW: Your function says it will return int but the code has no return statement. That's a bug for sure.
The shown function (according to its name) should create a new node and apend it at the end of the list represented by the pointer to a pointer to a node of that list. (I doubt however, that it actually does, agreeing with comments...)
Since the list might be empty and that pointer to node hence not be pointing to an existing node, it is ncessary to be able to potentially change the pointer to the first elemet of that list away from NULL to then point to the newly created node.
That is only possible if the parameter is not only a copy of the pointer to the first node but instead is a pointer to the pointer to the first node. Because in the second case you can dereference the pointer to pointer and actually modify the pointer to node.
Otherwise the list (if NULL) would always still point to NULL after the function call.

typedef struct declaration gives back an error

I do not understand what is wrong with the following piece of code. I am trying to create a linked list in C. I am creating a typedef struct which I call a person, then I declare a pointer that points to that structure and I am trying to allocate some memory for it to be able to store all its components. The compiler gives back an error saying that 'head' does not name a type.
typedef struct node {
int num;
struct node *next;
} person;
person *head = NULL;
head = (person*)malloc(sizeof(node));
Assuming the assignment to head is in a function, it is still incorrect as node is not a valid type or variable. It's either struct node but as you typedef'd that you should use person
head = malloc(sizeof(person));
But as the variable head is already of type person* you can also do
head = malloc(sizeof(*head));
which has the advantage you no longer need to know the exact type name (should you ever change it)
Also note that casting the result of malloc is not needed and unwanted.
You will have to check for the result being NULL though.

Linked-list is confusing

I am stuck, as I don't understand what is this code doing:
struct node
{
int info; /* This is the value or the data
in the node, as I understand */
struct node *next; /* This looks like a pointer. But
what is it doing in real life? */
} *last; /* What is this and why is it
outside the body? What is this
thing doing? */
I know that when a node is created, it has a value, and it is pointing to some other node
but I don't understand the syntax.
Is this a better way of writing the code above?
Is there a simpler way of writing the same struct for better understanding?
In my lectures they presume that the student has understanding of what they teach.
Well, we can explain this to you, but we can't understand it for you.
Code snippet you've provided is definition of variable last, being pointer to newly defined structure type node. It can be written other way as:
typedef struct _node_t {
int info;
node_t *next;
} node_t;
node_t *last;
This way we define typedef, which is, say, alias of type definition to some short name — in this particular case, it aliases structure of two fields as the name node_t. Wherever you define something as being of type node_t, you tell compiler that you mean 'this should be aforementioned structure of two fields', and node_t *last means 'variable last should be pointer to node_t type'.
So, back to syntax:
struct foo {
int a;
float b;
void *c;
} bar, *baz;
means 'Define structure type foo, and make it contain three fields — integer a, float-point b and untyped pointer c, then make variable bar to be of this structure type, and make variable baz to point to this structure type'.
Now to pointer. What you see is called 'recursive definition', e.g. type mentions itself in it's own definition. They are okay, if language supports them (C does), but one could avoid recursive definitions in linked list node structure by specifying next node pointer to be just untyped:
struct node_t {
int info;
void *next;
};
This way you no longer reference node_t type from node_t type, but that adds you some inconveniences when using this type (you have to explicitly cast next to node_t type, like ((*node_t)(last->next))->info instead of just last->next->info).
If you feel you need additional reference, consider taking a look at interactive online tutorials, like http://www.learn-c.org/ (I'm not affiliated).
that is the simplest way to write a linked list node , but why name it last ? name it node instead , this makes it more understandable , but here's how it works.
when a linked list is first created it contains only the root node (the first node in a linked list) , when you add a node , you fill the info field with the data that node will hold (note that info may be any kind of data , character , string , int ...) then set next to NULL , since that node is the last node in the list.
when you add another node , you change the value of next to point to the node you just added and you set the value of next to NULL in the node you just created because now that is the last node in the list .
you can repeat this to add as many nodes as your memory allow you to.
this link may help you to better understand structures
typedef struct marks {
int m;
struct marks *next;
} marks_t;
This way we define a structure so that a Linked List can be formed. Now we have defined the last variable next as a "structure pointer" which gives us the address of the next element in the list (i.e. as structure only)!
The last element does not point to any node (here marks structure) and hence the pointer variable has NULL value.
Now to define the first element:
marks_t *list;
if (list == NULL) {
list = (marks_t *) malloc(sizeof(marks_t));
}
list->m = 15;
list->next = NULL;
Now if we want to add an element next to this (i.e. second element):
marks_t *next1;
next1 = (marks_t *) malloc(sizeof(marks_t));
next1->m = 27;
next1->next = NULL;
list->next = next1; // Storing address of next1 structure in list

Deleting first node of linked list

I have to print a list of a set in c using linked lists (hence pointers). However,when I delete the first element of the list and try to print the list, it just displays a lot of addresses under each other. Any suggestions of what the problem might be? Thanks!
Delete function:
int delete(set_element* src, int elem){
if (src==NULL) {
fputs("The list is empty.\n", stderr);
}
set_element* currElement;
set_element* prevElement=NULL;
for (currElement=src; currElement!=NULL; prevElement=currElement, currElement=currElement->next) {
if(currElement->value==elem) {
if(prevElement==NULL){
printf("Head is deleted\n");
if(currElement->next!=NULL){
*src = *currElement->next;
} else {
destroy(currElement);
}
} else {
prevElement->next = currElement->next;
}
// free(currElement);
break;
}
}
return 1;
}
void print(set_element* start)
{
set_element *pt = start;
while(pt != NULL)
{
printf("%d, ",pt->value);
pt = pt->next;
}
}
If the list pointer is the same as a pointer to the first element then the list pointer is no longer valid when you free the first element.
There are two solutions to this problem:
Let all your list methods take a pointer to the list so they can update it when neccesary. The problem with this approach is that if you have a copy of the pointer in another variable then that pointer gets invalidated too.
Don't let your list pointer point to the first element. Let it point to a pointer to the first element.
Sample Code:'
typedef struct node_struct {
node_struct *next;
void *data;
} Node;
typedef struct {
Node *first;
} List;
This normally happens when you delete a pointer (actually a piece of the memory) which doesn't belong to you. Double-check your function to make sure you're not freeing the same pointer you already freed, or freeing a pointer you didn't create with "malloc".
Warning: This answer contains inferred code.
A typical linked list in C looks a little something like this:
typedef struct _list List;
typedef struct _list_node ListNode;
struct _list {
ListNode *head;
}
struct _list_node {
void *payload;
ListNode *next;
}
In order to correctly delete the first element from the list, the following sequence needs to take place:
List *aList; // contains a list
if (aList->head)
ListNode *newHead = aList->head->next;
delete_payload(aList->head->payload); // Depending on what the payload actually is
free(aList->head);
aList->head = newHead;
The order of operations here is significant! Attempting to move the head without first freeing the old value will lead to a memory leak; and freeing the old head without first obtaining the correct value for the new head creates undefined behaviour.
Addendum: Occasionally, the _list portion of the above code will be omitted altogether, leaving lists and list nodes as the same thing; but from the symptoms you are describing, I'm guessing this is probably not the case here.
In such a situation, however, the steps remain, essentially, the same, but without the aList-> bit.
Edit:
Now that I see your code, I can give you a more complete answer.
One of the key problems in your code is that it's all over the place. There is, however, one line in here that's particularly bad:
*src = *currElement->next;
This does not work, and is what is causing your crash.
In your case, the solution is either to wrap the linked list in some manner of container, like the struct _list construct above; or to rework your existing code to accept a pointer to a pointer to a set element, so that you can pass pointers to set elements (which is what you want to do) back.
In terms of performance, the two solutions are likely as close so as makes no odds, but using a wrapping list structure helps communicate intent. It also helps prevent other pointers to the list from becoming garbled as a result of head deletions, so there's that.

C Treenode pointers changing values with globals

So, here's the story. I'm trying to create a recursive descent parser that tokenizes a string and then creates a tree of nodes out of those tokens.
All of the pointers for my major classes are working... if you're worked with an RDP before then you know what I'm talking about with program -> statement -> assignStmt... etc. The idea being that the program node has a child that points to the statement node, etc.
Here's the problem. When I get to the end of the treenode I'm pointing to the actual tokens that the tokenizer created from the string.
So, let's say the string is:
firstvar = 1;
In this case there are 4 tokens [{id} firstvar], [{assignment} =], [{number} 1], [{scolon}]
And I want my assignStmt node to point to the non-decorator portions of that statement.. namely, child1 of assignStmt would be [{id} firstvar] and child2 would be [{number} 1]...
HOWEVER. When I assign child1 to [{id} firstvar], and then move onward to the next tokens, the value of child1 changes as I move forward. So, if I change my global token to the next token ( in this case [{assignment} =] ) then child1 of the assignStmt changes with it.
Why is this? What can I do?! Thank you!
TOKEN* getNextToken(void);
//only shown here to you know the return... it's working properly elsewhere
typedef struct node {
TOKEN *data;
struct node *child1, *child2, *child3, *child4, *parent;
} node;
TOKEN *token;
Symbol sym;
struct node *root;
void getsym()
{
token = getNextToken();
sym = token->sym;
}
int main()
{
getsym();
//So, right now, from getsym() the global token has the value {identifier; firstvar}
struct node* tempNode;
tempNode = (struct node*) calloc(1, sizeof(struct node));
tempNode->child1 = tempNode->child2 = tempNode->child3 = tempNode->child4 = NULL;
tempNode->data = token;
getsym();
//BUT NOW from getsym() the global token has the value {assignment; =}, and
//subsequently the tempNode->data has changed from what it should be
//{identifier; firstvar} to what the global token's new value is: {assignment; =}
}
Since i can't comment on this due to my low reputation i will add this answer and if have understood your problem you are probably passing a pointer to a function, and the problem is that you probably need a pointer to pointer instead of just a pointer.
in C when you pass values to a function you are passing them by value, not by reference, meaning that the function makes a local copy of that argument and it will work only with that local copy, the problem is that all the changes will affect only the local copy and when the function terminates all the changes will be lost if you will not handle this correctly.
You are returning a pointer to a global variable, and that pointer will always be the same even if you modify the global variable.
The solution is to either allocate a new object each time, or to not use pointers at all and return the structure directly and let the compiler handle copying of the structures internal values.

Resources