when to use to double pointers and pointers - 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.

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);
}

why my my function is using call by value method?

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.

Looking for Segmentation Fault in C script

Hi trying to learn C specifically how to use pointers.
I wrote this script to practice ideas I've learned, but it crashes with segmentation fault error.
Bit of research search suggests that I am trying to access something that I should not be accessing I think that is an uninitialized pointer but I can't find it.
#include <stdio.h>
struct IntItem {
struct IntItem* next;
int value;
};
struct IntList {
struct IntItem* head;
struct IntItem* tail;
};
void append_list(struct IntList* ls, int item){
struct IntItem* last = ls->tail;
struct IntItem addition = {NULL,item};
last->next = &addition;
ls->tail = &addition;
if (!ls->head) {
ls->head = &addition;
}
}
int sum(int x, int y){
return x + y;
}
int max(int x, int y){
return x*(x>y) + y*(y>x);
}
int reduce(struct IntList xs, int (*opy)(int, int)){
struct IntItem current = *xs.head;
int running = 0;
while (current.next) {
running = opy(running,current.value);
current = *current.next;
}
return running;
}
int main(void) {
struct IntList ls = {NULL, NULL};
printf("Start Script\n");
append_list(&ls, 1);
append_list(&ls, 2);
append_list(&ls, 3);
printf("List Complete\n");
printf("Sum: %i",reduce(ls,sum));
printf("Max: %i",reduce(ls,max));
return 0;
}
Hints:
When you call append_list(&ls, 1), then inside append_list, what is the value of last?
What does last->next = &addition do?
And for your next bug:
What happens to addition after append_list returns? What does that mean for pointers to it?

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 use pointer to access variables of public struct

I have a pointer to a class and I'm trying to use it to access the class' public struct. I've looked at access member var using ptr, as well as access memb struct from ptr class, but when you look at the links, it's not what I'm trying to do.
I'm having trouble doing something that will build. The examples in the code are without pointers, but I have a pointer to IFM to work with. Does anyone know how to use the pointer (to IFM) to access the public struct (in IFM)?
//snippet of code that is trying to access struct in IFM:
const IFM *pJunk = rData1.getM(); //this is fine
pJunk->JunkStruct::Junk.xs; //this doesn't work
The struct in IFM.h:
class IFM final : public IFO
{
public:
typedef struct JunkStruct
{
JunkStruct() = default;
~JunkStruct() = default;
JunkStruct(const IFM::JunkStruct&) = default;
JunkStruct(const double& first, const double& second, const double& third, const double& fourth, const double& fifth, const double& sixth) :
xs(first), ysk(second), xsk(third), ys(fourth), x(fifth), y(sixth)
{}
IFM::JunkStruct& operator=(const IFM::JunkStruct&) = default;
// Initialized
double xs = 1.0;
double ys = 0.0;
double xsk = 0.0;
double ysk = 1.0;
double x = 0.0;
double y = 0.0;
} Junk;
...
OPs member is private. It is designed to be hidden. Nothing to see here.
The struct is just a type. If no members in IFM is of type JunkStruct there is no data there to be accessed. To use that inner type you can see this minimal example
struct Outer
{
struct Inner{
int innerMember;
};
};
int main() {
Outer::Inner inner;
inner.innerMember = 4;
std::cout << inner.innerMember << "\n";
Outer outer;
Outer* outerP = &outer;
outer-> No access to innerMember, it does not exist.
}
If on the other hand, the struct would not be a typedef but just a struct, that definition would be akin to:
struct Outer
{
struct Inner{
int innerMember;
};
Inner outerMemberInner; //
};
int main() {
Outer outer;
Outer* outerP = &outer;
outerP->outerMemberInner.innerMember = 4;
// this might be what you are looking for
std::cout << outerP->outerMemberInner.innerMember;
}
With Junk as outerMemberInner.
The type JunkStruct aliased Junk belongs to the type IFM, not to IFM objects or pointer.

Resources