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.
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
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...
}
struct node {
int data;
struct node *next,*prev;
};
void insert(struct node *head,int data){
if(head == NULL){
head = (node *)malloc(sizeof(node));
--- code continues-----
I just want to know the difference between
head = (node *)malloc(sizeof(node)); and struct node *head = malloc(sizeof(struct node));
And if I pass **head as a parameter of the insert function what does it do ?
The difference between:
head = (node *)malloc(sizeof(node));
struct node *head = malloc(sizeof(struct node));
is that a C compiler will reject the first and allow the second, but a C++ compiler will accept the first and reject the second.
In C, the code shown does not create a type name node when you define or declare struct node. You would need to add typedef struct node node; in the C source. C++ automatically creates the type name node from the definition of struct node. (A C++ compiler rejects the second because of the implicit cast from void * to struct node *; C++ does not allow that, and would require struct node *head = (struct node *)malloc(sizeof(struct node));)
And if I pass **head as a parameter of the insert function, what does it do?
You'd have to adjust the body of the function, but it would allow you to change the location of the head of the list in the calling function.
The answer for your first question is:
head=(node *)malloc(sizeof(node));
malloc() returns a pointer of type void so here you are explicitly converting it to a pointer of type node .But remember, in C a pointer of type void() converts implicitly into the type of pointer that it is assign to. So if you write like:
head=malloc(sizeof(node));
It will stil work correctly. But with the C++ compiler it is not the case, In C++ pointer of type void is not implicitly cast to the type of pointer that it it assign to.
Also to answer your question,
void insert(struct node *head,int data)
If you pass **head as parameter it will show an error declaring that the type of operator is not matched. This is because you had declared it as struct node *head not as struct node **head.
If you type in
typedef struct node{
int data;
struct node *next, *prev;
} node;
the compiler will accept your head = (node *)malloc(sizeof(node)); code. Remember that typedef allows you to use the struct the same way it's used in C++.
Technically there isn't a difference between sizeof(node) and sizeof(struct node) (at least in C++), since both will return the size of the struct.
In C however it's mandatory to write struct node, just like it's mandatory to write struct node when declaring a variable of that type, simply because there is no type node.
C only understands primitives (int, char, long) and custom types declared with struct. Every C compiler is very strict with this keyword struct and assumes you're talking about a variable if you forget it.
Regarding your second question: You can't. You can't pass a pointer to a pointer to a function, which only accepts a regular pointer, unless you cast it. In that case however, it will point to a completely arbitrary position on the stack (where your pointer is located) and probably make your program crash.
create (struct node **p)
{
struct node *temp,*q;
int n;
printf("enter the length of link list");
scanf("%d".&n);
while(n>0)
{
if(*p == NULL)
{
*p=(struct node*)malloc(sizeof(struct node*));
printf("enter the element");
scanf("%d".&((*p)->data));
(*p)->next=NULL;
}
else
q=*p;
while(q->next=NULL)
q=q->next;
Im not sure i got the concept of Linked List properly. What im trying to do is to create a linked list which receives the integer 6 as it's first "data". instead i get this access violation error when trying to write in the integer into the first node's data. is there something specific i missed here?
///////////////////////////////
typedef struct List_Node
{
int data;
struct List_Node* next;
}List_Node;
typedef struct List
{
List_Node* head;
}List;
////////////////////////////////
List* create_list();
void print_list(List_Node *x);
void add_to_node(List_Node *a,int val);
////////////////////////////////
void main()
{
List *a = create_list();
List_Node *ind = a->head;
printf("List:\n");
add_to_node(ind,6);
}
void print_list(List_Node *a)
{
while(a != NULL)
{
printf("%d \n",a->data);
a = a->next;
}
return;
}
void add_to_node(List_Node *a,int val)
{
a->data = val;
}
struct List* create_list()
{
struct List* list = (List*) malloc(sizeof(List));
list->head = NULL;
return list;
}
The code is dereferencing a NULL pointer as a->head is NULL:
list->head = NULL; /* inside create_list()` and 'list' returned to ...*/
List_Node *ind = a->head; /* ... inside main(), and then passed to */
add_to_node(ind,6); /* add_to_node() ... */
a->data = val; /* and dereferenced inside add_to_node(). */
Dereferencing a NULL pointer is undefined behaviour. To correct, malloc() memory for a List_Node and assign to a->head. Recommend creating an add_node() function that allocates memory and assigns the new int value to newly malloc()d node.
Do I cast the result of malloc?
As all have pointed out, you are dereferencing a NULL pointer as your list->head contains NULL.
Another thing I should point out is that, you are creating a List. but not any Node. There is no node in the list. You have to allocate memory for a Node and then use it.
So, instead of add_to_node(), you may use a function add_node that will take the list or the head and the value as parameters, create a node(i.e. allocating memory for the node), set the value and add it to the list.
Also, in your case, the structure List is redundant as it contains only one member. instead you can simply use List_node* head.
What you are doing:
In create_list:
Allocating memory for a List pointer.
Setting the list's head to NULL.
In add_to_node:
Setting the specified node pointer's data element to the specified val.
In main:
Creating a List pointer a by calling create_list. This list has a NULL head.
Initializing a List_Node pointer, ind, to point to the created list's head (which is NULL).
Trying to set ind's data element to 6 by calling add_to_node.
This is where your program is causing the access violation exception.
ind = NULL. Therefore NULL->data = undefined behaviour.
What you should be doing:
In create_list:
Allocate memory for a List pointer, say linked_list.
Allocate memory for linked_list's head pointer.
For the linked_list's head, initialize data and the next pointer to 0 and NULL respectively.
In add_to_node:
Do the same thing you're doing now.
In main:
Create a List pointer a by calling create_list. Now, this list will have a valid, initialized NULL head, but with no meaningful data.
Set the list's head data by calling add_to_node(a->head, 6);.
Note: This will only ensure you have a head node in your list. Nowhere are you creating additional nodes.
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.