why do we use pointer to a pointer - c

#include <stdio.h>
#include <stdlib.h>
struct llnode {
int data;
struct llnode *next;
};
void insert (struct llnode **head, int data);
int
main () {
struct llnode *head;
head = NULL;
printf("starting\n");
insert(&head, 4);
return 0;
}
void
insert (**struct llnode **head**, int data) {--> why do we use a pointer to a pointer
printf("insert %0d\n", data);
struct llnode *l = malloc(sizeof(struct llnode));
l->data = data;
l->next = NULL;
if (*head == NULL) {
*head = l;
} else {
struct llnode *tmp = *head;
while (tmp->next != NULL) {
tmp = tmp->next;
}
tmp->next = l;
}
}
1)Why do we use a pointer to pointer. Can it be explained with an example.
2)How to do insertion into a doubly linked list?
HElp me and please explain how to print

Often a pointer to pointer is used when you want to pass to a function a pointer that the function can change.

Pointer to pointer or double pointer are variables whose possible values ​​are memory addresses of other pointer variables.
You have a good answer here, I think he can explain it better than me.
Also you can check this link.

Related

Double pointer in linked list

I almost figured out this code, but there are two details I can't figure out.
I found this code on YouTube.
source: https://www.youtube.com/watch?v=VOpjAHCee7c
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int vaule;
struct node *next;
}node_t;
void printlist(node_t *head)
{
node_t *temp = head;
while(temp != NULL)
{
printf("%d - ", temp->vaule);
temp = temp->next;
}
printf("\n");
}
node_t *create_node(int var)
{
node_t *res = malloc(sizeof(node_t));
res->vaule = var;
res->next = NULL;
return res;
}
node_t *insert_at_head(node_t **head, node_t *node_to_insert)
{
node_to_insert->next = *head;
*head = node_to_insert;
return node_to_insert;
}
void find_node()
int main()
{
node_t *tmp;
node_t *head = NULL;
for(int i = 0; i < 15; i++)
{
tmp = create_node(i);
head = insert_at_head(&head, tmp);
}
printlist(head);
return 0;
}
1) Why do we use the nested struct?
typedef struct node{
int vaule;
struct node *next;
}node_t;
I know about nested structures but I didn't understand why we use it here.
2) Why do we use double pointer?
node_t *insert_at_head(node_t **head, node_t *node_to_insert)
{
node_to_insert->next = *head;
*head = node_to_insert;
return node_to_insert;
}
if I change this code like this:
node_t *insert_at_head(node_t *head, node_t *node_to_insert)
{
node_to_insert->next = head;
return node_to_insert;
}
then nothing will change
Why do we use the nested struct?It's not a nested struct. struct node *next is a pointer, and as its name indidcates, it points to the next element.
Why do we use double pointer? Read this: How do I modify a pointer that has been passed into a function in C?
1)Why do we use the nested struct?
It is not a nested struct, but a linked list. Each node has a pointer to the next node (or to NULL for the last node of a list
2)Why do we use double pointer?
C only passes parameters by value. The idiomatic ways to change a variable from the caller are:
assign the return value to that variable. It is the best way, but you can only return one single value that way
pass a pointer to the variable and use the pointer to change the value. As we want to change the value of head which is already a pointer, we have to pass a pointer to pointer.
Here the write of the code has decided to change the passed header to clearly show that it is an input/output parameter, and also returns it because it had no better value to return.

Segmentation Fault 11: 10

I have a problem with solving a problem. I get continue the segmentation fault: 11 error, while I try this code. And every time I change the code the error pops up, and I don't know where the flaw is, so I would be greatfull if anyone sees the flaw.
I thank you in advance.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "dbg.h"
typedef struct node{
char *data;
struct node *next;
} node_t;
node_t **push(node_t **head, char *data){
node_t *new_node;
new_node = malloc(sizeof(node_t));
new_node->data = data;
new_node->next = *head;
*head = new_node;
free(new_node);
return head;
}
int main(int argc, char *argv[])
{
node_t **head;
char *data = "hoi";
char *data2 = "hallo";
head = malloc(20 * sizeof(node_t));
head = push(head, data);
head = push(head, data2);
printf("%s\n",(*head)[1].data);
free(head);
return 0;
}
Flaws:
Your push() function assigns the value of new_node to *head, making it accessible to the invoker of push(), but at the end of the function you free new_node, making it a dangling pointer. That's a good ground for segmentation faults.
head is a pointer to a pointer but is assigned the result of a malloc() invokation that seems to indicate that it should be a pointer to a node.
Your design is confusing: do you want to allocate the memory in push() or in main(). Certainly, both is not a good choice.
You are pointing to constant strings with non constant pointers. This is dangerous. Writing to the constant strings through these pointers could lead to segmentation faults too.
Here is a version of your program that works:
#include <stdio.h>
#include <stdlib.h>
struct node {
const char *data;
struct node *next;
};
static struct node *push(struct node *head, const char *data) {
struct node *node;
node = malloc(sizeof *node);
node->data = data;
node->next = head;
return node;
}
int main(int argc, char *argv[])
{
struct node *head = NULL;
const char *data = "hoi";
const char *data2 = "hallo";
head = push(head, data);
head = push(head, data2);
struct node *node = head;
while (node) {
printf("%s\n", node->data);
node = node->next;
}
return 0;
}
Note that I implemented a LIFO structure, aka. a stack, because a push() function usually applies to a stack.
A logical next step for you would be to implement the pop() function. Typically, I would recommend that pop() frees the node and returns the data. That would provide a nice symmetry for your API.

can't use a function with a 'pointer to pointer' input in another function. In C language

this code supposed to print : 'tree two one'
but it doesn't work. (the new_nod isn't added to the front of mylist)
anybody knows why? (actually in this code i wanted to use a function with a pointer to pointer input in another function but it didn't work(no changes applied to the mylist).
but it works when i'm using add_front function straightly in main.
#include <stdio.h>
#include <stdlib.h>
struct node{
char *word;
struct node *next;
};
struct node* create_node(char *str){
struct node *s;
s = (struct node *)malloc(sizeof(struct node));
if(s==NULL){
printf("couldn't malloc :(\n");
exit(-1);
}
s->word = str;
s->next = NULL;
return s;
}
void print_node(struct node *list){
struct node *current;
for(current = list; current !=NULL; current = current->next)
printf("%s ", current->word);
}
void add_front(struct node **list, struct node *new_node){
new_node->next= *list;
*list = new_node;}
void func(struct node*list, struct node*new_node){
add_front(&list, new_node);
}
int main()
{
struct node* mylist = create_node("one");
mylist->next = create_node("two");
struct node *new_node = create_node("tree");
func(mylist, new_node);
print_node(mylist);
}
Your add_front accepts a pointer to a pointer and other than missing a check for NULL is pretty much okay. But let's take a look at this:
void func(struct node*list, struct node*new_node){
add_front(&list, new_node);
}
What is add_front modifying here? The local pointer list. Which is just a copy of mylist in main.
So you haven't changed what mylist is pointing to.

C Segmentation Fault (core dumped) Linked List

I keep getting Segmentation Fault (core dumped) run time error and I can't figure out why.
My code:
struct Node
{
void *next;
void *val;
};
typedef struct Node* NodePtr;
struct List
{
NodePtr head;
};
typedef struct List* ListPtr;
ListPtr create()
{
ListPtr ptr = malloc(sizeof(struct List));
return ptr;
}
int insert(ListPtr list, void *obj)
{
NodePtr newObj = malloc(sizeof(struct Node));
//Cast next as a self referencing Node
newObj->next = (NodePtr) newObj->next;
//Point to beginning of list
NodePtr current = list->head;
if(list->head == NULL)
{
newObj->val = obj;
list->head->next = newObj;
newObj->next = NULL;
return 1;
}
return 0;
}
int main(int argc, char *argv[])
{
int x = 2;
int *p = &x;
ListPtr thing = create();
insert(thing, p);
return 0;
}
The error is here: list->head->next = newObj after some debugging. I thought I had to allocate memory for list->head->next, but when I added the code in for that it still gave me the same error. Am I casting it wrong or not allocating memory correctly? Any help would be appreciated, thanks!
Just put this together, runs fine.
#include <stdlib.h>
#include <stdio.h>
struct Node {
void *next;
void *val;
};
typedef struct Node* NodePtr;
struct List {
NodePtr head;
};
typedef struct List* ListPtr;
ListPtr CreateList() {
ListPtr ptr = malloc(sizeof(struct List));
return ptr;
}
void Insert(ListPtr list, void *obj) {
// create and initialize new node
NodePtr newObj = malloc(sizeof(struct Node));
newObj->val = obj;
newObj->next = NULL;
//Point to beginning of list
NodePtr curr = list->head;
// Add node to the list
if(curr == NULL) // if no head node, make newObj the head node
{
list->head = newObj;
}
else{ // otherwise traverse the list until you find the last node (the one that points to a null as the next)
while(1) {
if(curr->next != NULL) {
curr = curr -> next;
} else {
curr->next = newObj;
}
list->head = newObj;
newObj->val = obj;
list->head->next = newObj;
newObj->next = NULL;
}
}
}
int main() {
int x = 2;
int *p = &x;
ListPtr thing = CreateList();
Insert(thing, p);
return 0;
}
You check if list->head is NULL and then do some operations with that. Change that to if(list->head != NULL)
{
...
}
At a thought, malloc does not guarantee allocated memory is empty. It's good practice to set all values where they matter after allocation.
list->head is probably not null
also : newObj->next = (NodePtr) newObj->next;
doesn't set to a rational value, it sets to whatever memory was set - were you intending newObj->next = (NodePtr) newObj; ?
list->head should not be referenced if null. list->head->next will only be valid if it's not null.
if you actually want to build a list,
newObj->val = obj;
if (list->head == NULL) { newObj->next = list->head; }
list->head = newObj;
either that or travel down list->head->next chain until next is null, and set that to be newObj->next. If that way then it's possibly a good idea, newObj->next should be set to NULL and not itself.
Might want to figure out how your list will behave - is it circular? does it grow from the head (list->head) or tail (last ->next) ? Do you spot the tail when listObject->next == NULL or when listObject->next == listObject ?
I realize that this answer is mostly stylistic. But I do think that (bad) style and (bad) habits are an (important) part of (bad) programming. Summing it up ...
(in most cases) typedefs are not needed; they just introduce an alias for something that already existed.
[rule of seven] human readers have a limited amount of identifiers ("names") that they can keep track of. This could be 7. Minimising the number of distinct words makes reading easier.
also, the reader has to remember that xPtr and xNode are related (typeof *xPtr === typeof xNode)
when reading source code, keywords and special character tokens (such as operators) don't count as an identifier, since you do not have to remember them. (Syntax-highligting helps, too)
if there is only one way of expressing your program, there is no possibility for errors like iPtr *p; p = (qPtr) malloc (sizeof xNode);
creating yet another struct (+typedefs for it), just to accomodate a root pointer will clobber up your mental namespace even more.
Now a rework of the (intended) code:
#include <stdio.h>
#include <stdlib.h>
struct node {
struct node *next;
void *payload;
};
struct node *root=NULL;
void initialize() { /* nothing .... */ }
int insert(struct node **pp, void *pv) {
struct node *p;
p = malloc(sizeof *p);
if (!p) { /* handle error */ return -1; }
p->payload = pv;
p->next = *pp;
*pp = p;
return 1; /* inserted one element */
}
int main(void)
{
int i;
i=666;
/* note: this function call will pass a pointer to a local variable `i`
** to the insert() function, which will remember it.
** This is generally a bad idea, to say the least.
*/
insert( &root, &i);
return 0;
}

Passing typedef structure as call by reference in C

I am trying to create a linked list in C and my code is as below.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
}node_t;
void insert_into_list(node_t *,int);
void print_list(node_t *);
node_t *create_node(int );
void insert_into_list(node_t *head, int value){
node_t *temp ;
temp = create_node(value);
if(head == NULL){
printf("Inserting node for the first time\n");
head = temp;
}else {
head->next = temp;
}
}
void print_list(node_t *head){
node_t *current = head;
while(current!=NULL){
printf("%d----->",current->data);
current = current->next;
}
printf("NULL");
}
node_t *create_node(int value){
node_t *new_node = malloc(sizeof(node_t));
if(new_node==NULL){
printf("Memory allocation failed for the list creation. :(");
return NULL;
}
new_node->data = value;
new_node->next = NULL;
return new_node;
}
int main(int argc, char *argv[]) {
node_t *head = NULL;
insert_into_list(head,10);
if(head==NULL){
printf("Still head is NULL :(");
}else{
printf("Head is not NULL:)");
}
print_list(head);
return 0;
}
In main, I am calling insert_into_list and even after successful memory allocation, i am not able to get the head value with the newly created node. Still showing the value as NULL.
I have debugged with gdb and found that upto below code, head is not NULL
printf("Inserting node for the first time\n");
head = temp;
I thought I am passing by reference and expected the value to get reflected in the caller function.
Please correct me.
If you want to pass by reference (or rather, the equivalent) in C you must pass a pointer. To pass a pointer by reference you have to pass a pointer to the pointer.
So in e.g. insert_into_list you must declare head as a pointer to a pointer:
void insert_into_list(node_t **head, int value)
And use the dereference operator when accessing the head variable.
You call it using the address-of operator &:
node_t *head = NULL;
insert_into_list(&head,10);

Resources