I dont understand the cause of the segmentation fault here.
The code is:
struct node {
int data;
struct node* next;
};
void add(int a,struct node *lista)
{
struct node *p;
p=(struct node*)malloc(sizeof(struct node*));
p->data=a;
p->next=NULL;
while(lista->next!=NULL) <--- The segmentation fault is here.
lista=lista->next;
lista->next=p;
return lista;
}
int main(void)
{
struct node *list=NULL;
list_print(list);
list=node123();
list_print(list);
add(7, &list);
list_print(list);
return 0;
}
the add function which adds a new node to the end of the list worked perfectly like this on a friends computer and setup. I get segmentation fault. i think the problem is the lista->next expression but I don't understand why. Any ideas?
void add(int a,struct node *lista)... 2nd parameter is a struct node pointer.
struct node *list=NULL; -- list is a struct node pointer.
add(7, &list); -- &list is a struct node **; this is incorrect and likely to cause add()'s `while(lista->next!=NULL) to fail its dereference.
p = (struct node*)malloc(sizeof(struct node*));
This is certainly wrong. You must not allocate memory sized as the pointer itself, but as big as the actual structure. Use
p = malloc(sizeof(struct node));
or even better
p = malloc(sizeof(*p));
And don't for the love of God cast the return value of malloc().
Also, you declare list as struct node *, and your add() function also expects a struct node * - so it's erronous to pass its address to the function. Instead of
add(7, &list);
write
add(7, list);
You're passing the address of list, but the funciton takes only a pointer, in order to pass 'list' by reference, You've got to chagne the decliration of add to:
void add(int a,struct node **lista);
and then use (*lista) instead of just 'list' . ex: (*lista)->next ...
You declared 'add' to not return any type of data (void). but you're returning 'list'. either make the function work on a pointer to a pointer to 'list' (taking **list as a parameter instead of *list). or make it return a list type: struct list* add(
1 - you have to check if lista is not null before writhin lista->next
2 - There is an error in the malloc :
p=(struct node*)malloc(sizeof(struct node));
the size to allocate is the size of a node, you allocated the size of a pointer struct node*.
3 - add(7 , lista) not add(7 , &lista) because lista is already a pointer.
Related
In creating a linked list we make a node structure and it consists of both data and a pointer to the next node. Later when we make a function to append elements onto the linked list, we make a temporary node to store the inputted data.
Let’s consider the following program-
#include<stdio.h>
struct node
{
int data;
struct node* link;
}
struct node* root=NULL;
void main(append)
{
struct node* temp;
temp= (struct node*)malloc(sizeof(struct node))
.....
}
My first question set:
In line 11, why do we need to mention (struct node*) before the malloc function?
What is the significance of that?
My second question set:
If we are making a doubly linked list which would have a node structure consisting of 2 pointers (for next and previous node), would we also initialize a pointer (for traversing the list) of the struct node type?
Is there a different way to initialize the pointer in that case?
The significance is to make bugs in your program,
The malloc will return void* and when you assign to your struct somthing* it will convert automaticlly.
You simply don't cast the result of malloc as it returns void* . There is one fine explanation here
A better solution might be :
struct node *temp;
temp = malloc(sizeof *temp);
why do we need to mention '(struct node*)' before the malloc function,
what is the significance of that?
By writing (struct node*) before the malloc function, you are type-casting the return value to the specified type. The cast here is optional and often frowned upon.
if we are making a doubly linked list which would have a node
structure consisting of 2 pointers(...
When making a doubly linked list, you should declare something like:
struct node {
int data;
struct node *next;
struct node *previous;
};
You can allocate space for a node by using the malloc function. The next and previous pointers are again pointers to struct nodes. Call malloc again to allocate space for the next element. For the first node, the previous should be NULL and for the last node, next should be NULL. Here is one implementation.
This is the because the return type of malloc is void*. (struct node*) is a cast using which you tell the compiler that you want to treat the value returned by malloc as a pointer to struct node.
For double linked list you can use,
struct node
{
int data;
struct node *next,*prev;
};
int main()
{
struct node *new_node=(struct node *)malloc(sizeof(node));
}
malloc returns the void pointer(can be checked and verified at the header ), and so the type casting is necessary while assigning it to the other type of variable.
Request you to read at the link https://www.tutorialspoint.com/cprogramming/c_type_casting.htm
I'm working with linked lists. I'm having trouble accessing the data contained in a struct through a pointer. Here is my code:
void insertNode(Node **head, int num) {
Node *newNode = malloc(sizeof(Node));
newNode -> num = num;
while (head->next) { <-----problematic code
}
}
I've passed the address of the head pointer of the list into the function.
Node *list = malloc(arraySize * sizeof(Node));
Node *head = list;
insertNode(&head, randNum);
I keep getting an error that says "request for member "next" in something not a structure or union.
Node **head is a pointer to a pointer to a Node. So head-> is dereferencing a pointer to a pointer and therefore gives you a pointer. A pointer is not a struct or union, hence the error. You can use:
(*head)->
to dereference the underlying node.
Try (*head)->next in your loop.
Reason is simple, you send Node** but expect that it will work like a Node*, which is not correct.
For example, I have a function:
void build()
{
struct Node *node;
node = (struct Node*)malloc(sizeof(struct Node));
}
Is it possible to access the pointer "node" from the outside?
C is a pretty straightforward and simple language. The only choice you have is to explicitlly put the node value somewhere, eiter:
global variable
parameters on the function
return value
Options 2 and 3 are the most common ones. As an argument to the function:
void build(struct Node **node_param)
{
struct Node *node;
node = (struct Node*)malloc(sizeof(struct Node));
*node_param = node;
}
For option 3 can be simply:
struct Node * build()
{
struct Node *node;
node = (struct Node*)malloc(sizeof(struct Node));
return node;
}
You can either create a standalone variable or create an struct with more fields in case you have many values to return from your function.
Is it possible to access the pointer "node" from the outside?
No, not this exact pointer since you don't know th memory address returned by malloc. You can access the Node instance pointed to by *node if you return initialized pointer out of the function or you pass it as an argument to this function, initialize inside the function and use after this.
example:
// pass pointer to pointer, so we will change original pointer not a copy
void build( struct Node **nodePtr)
{
struct Node *node;
node = malloc( sizeof( struct Node));
// ^^^^
// no need to cast result of malloc in C
*nodePtr = node;
// the rest...
}
In the below code, I am trying to insert a node after a particular node. In the function, I will be giving as input the address of the previous node after which I want to insert the new node. The problem is in the 10th line of function insertAfter() - it says I cannot access *prev_ref->next.
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node* next;
};
void push(struct node **head_ref, int data)
{
struct node* newNode = (struct node*)malloc(sizeof(struct node)) ;
newNode->next= *head_ref;
newNode->data= data;
*head_ref= newNode;
}
void insertAfter(struct node **prev_ref, int data)
{
if(*prev_ref==NULL)
{
printf("prev ref cant be null");
return;
}
struct node * newNode;
newNode = (struct node*)malloc(sizeof(struct node)) ;
newNode->next= *prev_ref->next;
newNode->data= data;
*prev_ref->next= newNode;
}
void printList(struct node *node)
{
while (node != NULL)
{
printf(" %d ", node->data);
node = node->next;
}
}
main()
{
struct node* head = NULL;
push(&head, 7);
push(&head, 1);
insertAfter(&head, 8);
printf("\n Created Linked list is: ");
printList(head);
getchar();
return 0;
}
Do you know (*p).s is equivalent to p->s ? I would suggest you to try something like (*prev_ref)->next or (**prev_ref).next
You seem to dereference prev_ref three-levels deep instead of two.
pointer->field is dereference of a pointer, equivalent to (*pointer).field
So, **prev_ref->next; is in fact (***prev_ref).next;
Either drop one asterisk or use . instead of ->.
EDIT:
You seem to have skipped the parentheses we included in our answers.
-> has higher precedence than *.
The effect is:
(*prev_ref)->next
first uses '*' and finds the memory pointed to by prev_ref (let's call it memory location A),
then uses '->' to find memory pointed to by A, let's call it B,
then location of the the next field of the structure, offset by a set distance from B, let's call it C
and finally accesses (reads/writes) the value stored at C.
Now for *prev_ref->next
first, uses -> and finds the memory pointed to by prev_ref (A), just the same
then the location of the the next field of the structure, offset by a set distance from A, which happens to be an entirely random location in memory (because A stored a pointer to the structure, not the structure itself); let's call that location D.
Then it tries to find the memory location at wherever D pointed to, which is entirely random.
Now, the system won't let you do that, because it sees A is not where a structure lies, but where a pointer to a structure lies, hence the error message
And the fundamental reason of your problems is that you use pointers-to-pointers for no good reason. Nothing of this would have happened if you always used plain pointers. void push(struct node *head_ref, int data) , void insertAfter(struct node *prev_ref, int data), prev_ref->next etc. Managing pointers to pointers is tricky, error-prone (as you've experienced) and in 99% cases completely unnecessary.
Excuse the beginner level of this question. I have the following simple code, but it does not seem to run. It gets a segmentation fault. If I replace the pointer with a simple call to the actual variable, it runs fine... I'm not sure why.
struct node
{
int x;
struct node *left;
struct node *right;
};
int main()
{
struct node *root;
root->x = 42;
printf("Hello world. %d", root->x);
getchar();
return 0;
}
What is wrong with this code?
struct node *root;
root->x = 42;
You're dereferencing an uninitialized pointer. To allocate storage for the node:
struct node *root = malloc(sizeof(struct node));
You could also allocate a node on the stack:
struct node root;
root.x = 42;
In order to use a pointer to access something, the pointer must be pointing at that something. In order for the pointer to be pointing at that something, that something must exist. Creating a pointer does not create anything for it to point at. You must do so explicitly, either by dynamic allocation (malloc()), stack allocation (i.e. a local variable) or by pointing to something that already exists (e.g. a static instance, such as a global; a value that was passed in as a parameter; etc.).
After struct node *root; line add the
root = (sturct node*) malloc(sizeof(struct node));
Also, before Return 0 line add the
free(root);