why my my function is using call by value method? - pointers

I don't know why in last line it is printing data of first element instead of last element. I want explanation.
// A simple C program for traversal of a linked list
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
// This function prints contents of linked list starting from
// the given node
void printList(struct Node* n)
{
while (n != NULL) {
printf(" %d ", n->data);
n = n->next;
}
}
int main()
{
struct Node* head = NULL;
struct Node* second = NULL;
struct Node* third = NULL;
// allocate 3 nodes in the heap
head = (struct Node*)malloc(sizeof(struct Node));
second = (struct Node*)malloc(sizeof(struct Node));
third = (struct Node*)malloc(sizeof(struct Node));
head->data = 1; // assign data in first node
head->next = second; // Link first node with second
second->data = 2; // assign data to second node
second->next = third;
third->data = 3; // assign data to third node
third->next = NULL;
printList(head);
printf("%d",head->data);
return 0;
}
As the function is accepting pointers so it should be call by reference.
And in last loop of function when n pointer is equal to NULL.
But in last line of this code is printing data of first list of my linked list.

Actually what you are doing is not being done in the actual linked list, it not pass by reference
void printList(struct Node* n)
{
/* some code here */
}
void main()
{
/* all your code here */
printList(head);
}
so if you want to change the head in the actual linked list you will have to pass the address of the pointer head to the function
something like this
int append_list(node **head, int data)
{
while((*head)->next!=NULL)
{
(*head) = (*head)->next;
}
}
int main()
{
struct node *head = NULL;
/* add nodes */
print_list(&head);
}
so here is the modification in your code:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
// This function prints contents of linked list starting from
// the given node
void printList(struct Node** n)
{
while ((*n)->next != NULL) {
printf(" %d ", (*n)->data);
(*n) = (*n)->next;
}
}
int main()
{
struct Node* head = NULL;
struct Node* second = NULL;
struct Node* third = NULL;
// allocate 3 nodes in the heap
head = (struct Node*)malloc(sizeof(struct Node));
second = (struct Node*)malloc(sizeof(struct Node));
third = (struct Node*)malloc(sizeof(struct Node));
head->data = 1; // assign data in first node
head->next = second; // Link first node with second
second->data = 2; // assign data to second node
second->next = third;
third->data = 3; // assign data to third node
third->next = NULL;
printList(&head);
printf("%d",head->data);
return 0;
}
here the output will be
1 2 3
since you have used (*head) for the traversal you no longer have the access to your list and hence will get segmentation fault if you try to access
(*head)->next
But I would not suggest to do this since now you will not be able to deallocate the memory

There is no pass-by-reference in C, everything is pass-by-value. People use pointers to emulate pass-by-reference, and this works because you can use the passed-in pointer to get at the same underlying data item.
In other words, even though the passed-in pointer is a pass-by-value copy within the function, the fact that it has the same value as the original means that both point to the same thing.
However, if the thing you're trying to change is a pointer already, you need a pointer to a pointer to do this emulation.
I could give you the code to do this but, believe me, it's not want you want. It would mean that the list printing code would be destructive to the list itself, since the head would now point to NULL.
Here is some code instead which shows how to do something similar, one that uses this double-pointer method to change the pointer outside of the function:
#include <stdio.h>
#include <stdlib.h>
void allocateSomeMem(void **pPtr, size_t sz) {
*pPtr = malloc(sz);
}
int main(void) {
void *x = NULL;
printf("%p\n", x);
allocateSomeMem(&x, 42);
printf("%p\n", x);
}
You can see by the output that the pointer is being changed:
(nil)
0x55f9ce5f96b0
Now, obviously, you wouldn't do this for the simple example shown, it would be far easier just to return the new pointer and have it assigned to x. But this is just illustrative of the method to use.

Related

Double LinkList in data structure

When I create a double Linklist By using C(C99), if I add the code: struct DNonde***first**=NULL; on the main function when running Display function the parameter first = NULL. If I remove the additional code: struct DNonde *first = NULL; then structure point: first will normally running as the linklist's first node's address and the Display funtion will also normally running.
However the question is I am using the Create function to create double Linklist after the code:struct DNonde*first=NULL;thus, it will not influence the latter codes, and when I debug the codes it shows me that the double Linklist is created successfully but when in Display function the first = NULL. And why it cause that?
Below is the source code
#include "stdio.h"
#include "stdlib.h"
struct DNonde
{
struct DNonde *preview;
int data;
struct DNonde *next;
}*first=NULL;
void Create(int a[],int length)
{
struct DNonde*tem = NULL;
first =(struct DNonde*)malloc(sizeof(struct DNonde));
first->preview=NULL; first->data=a[0]; first->next=NULL;
struct DNonde *control = first;
for(int i=1;i<length;i++)
{
tem =(struct DNonde*)malloc(sizeof(struct DNonde));
control->next = tem;
tem->preview = control; tem->data = a[i]; tem->next=NULL;
control = tem;
}
}
void Display(struct DNonde*first)
{
do
{
printf("%d ",first->data);
first=first->next;
}while(first != NULL);
}
int main()
{
int a[]={1,3,4,5};
struct DNonde*first=NULL;
Create(a, 4);
Display(first);
}

when to use to double pointers and pointers

// A C program to demonstrate linked list based implementation of queue
#include <stdio.h>
#include <stdlib.h>
struct QNode {
int key;
struct QNode* next;
};
struct Queue {
struct QNode *front, *rear;
};
struct QNode* newNode(int k)
{
struct QNode* temp = (struct QNode*)malloc(sizeof(struct QNode));
temp->key = k;
temp->next = NULL;
return temp;
}
struct Queue* createQueue()
{
struct Queue* q = (struct Queue*)malloc(sizeof(struct Queue));
q->front = q->rear = NULL;
return q;
}
void enQueue(struct Queue* q, int k)
{
struct QNode* temp = newNode(k);
if (q->rear == NULL) {
q->front = q->rear = temp;
return;
}
q->rear->next = temp;
q->rear = temp;
}
void deQueue(struct Queue* q)
{
if (q->front == NULL)
return;
struct QNode* temp = q->front;
q->front = q->front->next;
if (q->front == NULL)
q->rear = NULL;
free(temp);
}
int main()
{
struct Queue* q = createQueue();
enQueue(q, 10);
enQueue(q, 20);
deQueue(q);
deQueue(q);
enQueue(q, 30);
enQueue(q, 40);
enQueue(q, 50);
deQueue(q);
printf("Queue Front : %d \n", q->front->key);
printf("Queue Rear : %d", q->rear->key);
return 0;
}
The above code is from geeksforgeeks website.
in function calls they used pointer to struct,
in function definition they passed pointer to struct.
how it works, I thought we need to use double pointers , otherwise > it is pass by value instead of pass by reference.
the above code works fine, but i have doubt about it.
In main there is a variable q declared which is a pointer to a struct. The variable q is used as the function argument which means the function receives a pointer to the struct. The function can dereference the pointer and modify the struct. The variable q is technically passed by value because its value is a pointer and that's what the function receives. But you have to remember that q points to a struct that could be modified by the function.
Because this situation causes some confusion some people have tried to introduce new terminology like "pass by sharing" or "object sharing" to distinguish it from passing primitive values like an `int' by value.
If you had passed a pointer to a pointer then the function could have modified the variable q declared in main and changed it so it points to a completely different struct. That would be (technically) pass by reference because you are passing a reference to the variable.

declaration in local vs global

#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node* link;
};
void insert_last(struct node **head, int value)
{
struct node* new = malloc(sizeof(struct node));
new->data = value;
if( !*head )
{
new->link = NULL;
*head = new;
}
else
{
struct node* last = *head;
while(last->link)
{
last = last->link;
}
new->link = NULL;
last->link = new;
}
}
struct node *head;
int main()
{
insert_last( & head, 5);
insert_last( & head, 10);
insert_last( & head, 15);
printf("%d ", head->data);
printf("%d ", head->link->data);
printf("%d ", head->link->link->data);
}
If I Declare struct node *head inside of the main the programm is not working.
what is the reason ?
> if i declare globally its working, otherwise not working.
> I repeating question because stackoverflow asking add more details(> If I Declare struct node *head in side of the main the programm is not working.
what is the reason ?
> if i declare globally its working, otherwise not working.)
There is a initialization bug: In insert_last(), the variable head is tested without having been initialized explicitely. If head is declared as global, it is located in a global section that is most probably initialized to 0 by the loader (when the program is started); if head is declared in the function main() then it is located in the stack of the function and is not set to 0.

Queue implementation throws incompatible pointer type error

I think I'm missing general concepts on structs and pointers. Hence, below code is producing 2 warnings/errors and I don't understand why.
Why is "queue->head = temp" producing following warning:
warning: assignment from incompatible pointer type [enabled by default]
Why is "queue->tail->next = temp" producing following error:
error: dereferencing pointer to incomplete type.
Note: The line "Node *temp = newNode(data)" does not throw any error/warnings so it's successful.
typedef struct {
int data;
struct Node *next;
} Node;
typedef struct {
struct Node *head;
struct Node *tail;
} Queue;
void enQueue(Queue *queue, int data)
{
// Create a new node
Node *temp = newNode(data);
// If queue is empty, then new node is both head and tail
if (queue->tail == NULL)
{
queue->head = temp;
queue->tail = temp;
return;
}
// Add the new node at the end of queue and change tail
queue->tail->next = temp;
queue->tail = temp;
}
How did you get this code to compile?
Your Node structure contains a pointer to another Node. In the way you declared your structure, the compiler does not know Node while parsing your structure definition. Hence, you must write:
1 typedef struct Node{
2 int data;
3 struct Node *next;
4 } Node;
In this way, the compiler knows how to handle your structure when parsing it. In line 3 it already knows that Nodeis structure. Since some of your code is missing, I created a minimal example that implements a super simple queue:
#include <stdlib.h>
#include <stdio.h>
#define MAX 5
typedef struct Node{
int data;
struct Node *next;
} Node;
typedef struct {
struct Node *head;
struct Node *tail;
} Queue;
Node* newNode(const int nodeData){
Node* tmp = malloc(sizeof(*tmp));
if (NULL == tmp){
printf("Could not allocate Node ... exiting");
exit(EXIT_FAILURE);
}
tmp->data = nodeData;
tmp->next = NULL;
return tmp;
}
void enQueue(Queue *queue, int data)
{
// Create a new node
Node *temp = newNode(data);
// If queue is empty, then new node is both head and tail
if (queue->tail == NULL)
{
printf("Queue is empty\n");
queue->head = temp;
queue->tail = temp;
return;
}
// Add the new node at the end of queue and change tail
queue->tail->next = temp;
queue->tail = temp;
}
void printQueue(Queue* q){
Node* tmp = q->head;
while (tmp != NULL){
printf("Value: %d\n", tmp->data);
tmp = tmp->next;
}
}
int main(void){
Queue q;
q.head = q.tail = NULL;
int i;
for (i = 0; i < MAX; ++i){
printf("%d is entered into the queue\n", i);
enQueue(&q, i);
}
printQueue(&q);
}

How do I convert my depth-first traversal code using recursion to the one using stack?

My data structures and stack operations are defined like this.
typedef struct AdjListNode{
int dest;
struct AdjListNode* next;
int visited;
}AdjListNode;
typedef struct AdjList{
struct AdjListNode* head;
}AdjList;
typedef struct Graph{
int V;
struct AdjList* array;
}Graph;
typedef struct Stack{
int top;
char items[MAX];
}Stack;
void Push(struct Stack *s,float val){
if(s->top == MAX-1){
printf("Error: Stack overflow.");
exit(1);
}else{
s->items[++(s->top)]=val;
}
}
float Pop(struct Stack *s){
if(s->top == -1){
printf("Error: Stack underflow");
exit(1);
}else{
return(s->items[(s->top)--]);
}
}
int isFull(struct Stack* s){
return s->top == MAX-1;
}
int isEmpty(struct Stack* s){
return s->top == -1;
}
And this function checks if there is a path from p to q
void FindPath_DepthFirstSearch(Graph* graph, int p, int q) {
AdjListNode* node = graph->array[p].head;
node->visited = 1;
// printf("%d\n", p);
if(p == q){
printf("Path found!\n");
exit(1);
}
while(node){
if (!graph->array[node->dest].head->visited)
FindPath_DepthFirstSearch(graph, node->dest, q);
node = node->next;
}
printf("Path not found!\n");
exit(1);
}
I'm fairly new to learning data strctures. The code works perfectly when I use recursion but I got stuck for a long time when I tried to implement this using stack. Can anyone help me with this? Thanks!
The basic idea when converting from a recursive definition to a loop-based one is that you store the data that you normally store in local variables on a stack (LIFO) container. Instead of recursing, you push additional elements on the stack. The code then looks like this:
function algorithm(args):
stack = new FIFO
# push initial state (e.g. root node for DFS)
stack.push(args)
# process all elements
while stack.has_elements():
# retrieve topmost element from stack
e = stack.pop()
# do something with the current element
e.frobnicate()
# push additional elements onto the stack
if e.condition1():
stack.push(e.derived1())
if e.condition2():
stack.push(e.derived2())

Resources