Accessing data structures created inside a function? - c

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...
}

Related

how to use a struct field with a double pointer variable (without a support variable)?

I have this struct in c
struct node{
int info;
struct node* link;
};
this procedure:
void example(struct node** head){
struct node* tmp;
tmp=*head;
tmp->info=0;
*head=tmp;
}
and call the procedure in the main with
example(&head);
so to modify head->info I need a support variable,there is another way without a support variable?
Use this:
void example(struct node** head){
(*head)->info=100;
}
It'll do the same as your example function.
By dereferencing struct node** we get struct node*, then we can simply access it's member by using -> arrow operator.
If you have a pointer to an object declared like
struct node *head;
head = malloc( sizeof( struct head ) );
then you can just write
head->info = 10;
So as the object info is passed by reference to the function example there is no great sense to declare the parameter of the function as pointer to pointer
void example(struct node** head){
^^^^^^^^^^^
You can define the function like
void example(struct node *head){
head->info=0;
}
You need to pass head by reference when head itself is changed in the function.
For example
void insert( struct node **head, int info )
{
struct node *tmp = malloc( sizeof( struct node ) );
tmp->link = *head;
tmp->info = info
*head = tmp;
//^^^^^^^^^^^
}
If you need to change the data member info using pointer to pointer head then at first you need to dereference it to get pointer to the object info like and then apply the operator ->. For example
( *head )->info = 0;
In C if you want to change an object (that in particularly can be a pointer) in a function you have to pass it by reference that in C means passing an object through a pointer to it.

Linked list node memory allocation

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

Access structs through pointers

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.

How to declare a linked list in c

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;

segmentation fault -- cant understand the cause of the fault

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.

Resources