I'm still having trouble understanding how to copy structs that include char* fields\other struct fields:
typedef struct node{
int id;
struct node* parent
char * nodeName;
struct node* nodes[100];
}NODE,*pNODE;
I want to use this function : pNODE copyNode(pNODE oldNode)
1. i know that first I should do allocation for the new pointer data , and do the followong:
pNODE newNode = (pNODE)calloc(1,sizeof(NODE));
newNode.id=oldNode.id
//for the string that I want to copy I should allocate and use strcpy - in order not to point at the same string
but now I'm lost regarding the parent node, how do I copy it ? if I just do : newNode.parent=oldNode.parent
I point at the same parent object, and if I change it's Id for example - it will change both the id of newNode and oldNode. how can I copy it?? without pointing at the same one?
and how can i copy the pointer array??
thank you!
Take a look at the memcopy function:
memcpy(oldNode.parent, newNode.parent, sizeof(node)).
Of course, you first need to allocate memory for the newNode's parent, using malloc (calloc doesn't make sense in this context - it's used for arrays)
newNode.parent = (NODE*)malloc(sizeof(NODE))
If you want to do a deep-copy (i.e. don't reuse referenced objects), you should go through the newNode struct and allocate memory for each pointer contained in the struct and then apply memcopy.
Related
I'd like to understand the difference between using a pointer and a value when it comes to referencing a struct inside another struct.
By that I mean, I can have those two declarations:
struct foo {
int bar;
};
struct fred {
struct foo barney;
struct foo *wilma;
}
It appears I can get the same behavior from both barney and wilma entries, as long as I de-reference accordingly when I access them. The barney case intuitively feels “wrong” but I cannot say why.
Am I just relying on some C undefined behavior? If not, what would be the reason(s) to opt for one style over the other?
The following code shows how I come to the conclusion both use cases are equivalent; neither clang nor gcc complain about anything.
#include <stdio.h>
#include <stdlib.h>
struct a_number {
int i;
};
struct s_w_ptr {
struct a_number *n;
};
struct s_w_val {
struct a_number n;
};
void store_via_ptr(struct s_w_ptr *swp, struct s_w_val *swv) {
struct a_number *i = malloc(sizeof(i));
i->i = 1;
swp->n = i;
swv->n = *i;
}
void store_via_val(struct s_w_ptr *swp, struct s_w_val *swv) {
struct a_number j;
j.i = 2;
swp->n = &j;
swv->n = j;
}
int main(void) {
struct s_w_ptr *swp = malloc(sizeof(swp));
struct s_w_val *swv = malloc(sizeof(swv));
store_via_ptr(swp, swv);
printf("p: %d | v: %d\n", swp->n->i, swv->n.i);
store_via_val(swp, swv);
printf("p: %d | v: %d\n", swp->n->i, swv->n.i);
}
It's perfectly valid to have both struct members in a struct and have pointers to struct in a struct. They must be used differently but both are legal.
Why have a struct in a struct ?
One reason is to group things together. For instance:
struct car
{
struct motor motor; // a struct with several members describing the motor
struct wheel wheel; // a struct with several members describing the wheels
...
}
struct car myCar = {....initializer...};
myCar.wheel = SomeOtherWheelModel; // Replace wheels in a single assign
myCar.wheel.pressure = 2.1; // Change a single wheel member
Why have a struct pointer in a struct?
One very obvious reason is that is can be used as an array of N structs by using dynamic allocation of N times the struct size.
Another typical example is linked lists where you have a pointer to a struct of the same type as the struct containing the pointer.
There are several advantages of having a struct in a struct instead of having a pointer to struct in a struct:
It requires less memory allocation. In the case where you have a pointer to a struct in a struct, the compiler will allocate memory to store the pointer to the struct within the parent struct and separately allocate the memory for the child struct.
Additional instructions are typically required to access the contents of the child struct. For example consider that the program is reading the contents of the child struct. If a struct within a struct is used, the program will apply an offset to the address of the variable and read the contents of that memory location. In the case of a pointer to a struct in a struct, the program will actually apply an offset to the parent struct variable address, fetch the address of the child struct, then read from memory the contents of the child struct.
A separate variable needs to be declared for both the parent and child struct and if an initializer is used, then a separate initializer is needed. In the case of a struct in a struct only one variable must be declared and a single initializer is used.
In cases where dynamic memory allocation is used, the developer must remember to deallocate memory for both the child and parent objects before the variables fall out of scope. In the case of struct in a struct the memory must be freed for only one variable.
Lastly, as is shown in the example, if a pointer is used, Null checking may be necessary to ensure that the pointer to the child struct has been initialized.
The primary advantages of having a pointer to a struct in a struct would be if you needed to replace the child struct with another struct within the program, such as a linked list. A less common case might be if the child struct can be of more than one type. In this case you might use a void * type for the child. I may also use a pointer within a struct to point to an array in case where the array pointed to may vary in size between instances.
Based on my knowledge the case shown in the example above, I would be inclined to use a struct in a struct, since both objects are of fixed size and type and since it appears that they would not need to be separated.
C structures can be used to group related data, such as the title of a book, its author, its assigned book number, and so on. But much of what we use structures for is creating data structures (in a different sense of the word “structure”) in memory.
Consider that the book’s author has a name, a date of birth, other biographical information, a list of books they have written, and more. We could include in the struct book a struct author that would contain all this information. But, if the author has written a hundred books, we could have 100 copies of all that information, one copy in each struct book. Further, we cannot continue the “contain the data inside the structure directly” model with the struct author, because it cannot contain a struct book for each book the author publishes if those struct book members also have to contain the struct author for the author—every object would have to contain itself.
It is more efficient to create one struct author and have each struct book for that author to link to their struct author.
Another example is that we use pointers to create data structures for efficient access to data. If we are reading data for thousands of items and want to keep them sorted by name, one option is to allocate memory for some number of structures, read the data, and sort the data. When new data is read and we have used all the memory we allocated, we allocate new memory, copy all the old data to the new memory if necessary, and move some of the data so we can insert the new data in its proper place. However, we have many better options than that. We can use linked lists, binary trees, other kinds of trees, and hash tables.
These data structures effectively require using pointers. A binary tree will have a root node, and each node contains two pointers, one to a subtree of nodes that are earlier than it in the sorting order and another to a subtree of nodes that are later than it. We can look up items in the tree by following pointers to earlier or later nodes to find the right position. And we can insert items by changing a few pointers. If the tree happens to become unbalanced, we can rearrange nodes in the tree by changing pointers. The bulk of the data in the nodes does not have to be changed or copied, just some pointers.
We can also use pointers to have multiple structures for the same data. All the data about books could be stored in one place, and a tree ordered by name could contain nodes in which each node contained a pointer to the book structure and two pointers to subtrees. We could have one tree like this ordered by title of the book and another tree ordered by the name of the author and another tree ordered by the assigned book number. Then we can efficiently look up a book by title or author or number, but there is only one master copy of the complete book data, in the struct book objects. The look-up data is in the tree, which contains only pointers. That is much more efficient than copying all of the struct book data for each tree.
So the reasons we choose between use structures or pointers as members is not whether the C syntax allows us to refer to the data or not—we can get to the data in both cases. The reasons are because one method requires embedding data, which is inflexible and requires copying data, and the other method is flexible and efficient.
Let's consider at first this function
void store_via_ptr(struct s_w_ptr *swp, struct s_w_val *swv) {
struct a_number *i = malloc(sizeof(i));
i->i = 1;
swp->n = i;
swv->n = *i;
}
This declaration
struct a_number *i = malloc(sizeof(i));
is equivalent to the following declaration
struct a_number *i = malloc(sizeof( struct a_number * ));
So in general the function can invoke undefined behavior when sizeof( struct a_number ) is greater than sizeof( struct a_number * ).
It seems you mean
struct a_number *i = malloc(sizeof( *i ) );
^^^
If you will split the function in two functions for each its parameter like
void store_via_ptr1( struct s_w_ptr *swp ) {
struct a_number *i = malloc(sizeof( *i ) );
i->i = 1;
swp->n = i;
}
and
void store_via_ptr( struct s_w_val *swv ) {
struct a_number *i = malloc(sizeof( *i));
i->i = 1;
swv->n = *i;
}
then in the first function the object pointed to by the pointer swp will need to remember to free the allocated memory within the function. Otherwise there will be a memory leak.
The second function already produces a memory leak because the allocated memory was not freed.
Now let's consider the second function
void store_via_val(struct s_w_ptr *swp, struct s_w_val *swv) {
struct a_number j;
j.i = 2;
swp->n = &j;
swv->n = j;
}
Here the pointer swp->n will point to a local object j. So after exiting the function this pointer will be invalid because the pointed object will not be alive.
So the both functions are incorrect. Instead you could write the following functions
int store_via_ptr(struct s_w_ptr *swp ) {
swp->n = malloc( sizeof( *swp->n ) );
int success = swp->n != NULL;
if ( success ) swp->n->i = 1;
return success;
}
and
void store_via_val( struct s_w_val *swv ) {
swv->n.i = 2;
}
When to include a whole object of a structure type in another object of a structure type or to use a pointer to an object of a structure type within other object of a structure type depends on the design and context where such objects are used.
For example consider a structure struct Point
struct Point
{
int x;
int y;
};
In this case if you want to declare a structure struct Rectangle then it is natural to define it like
struct Rectangle
{
struct Point top_left;
struct Point bottom_right;
};
On the other hand, if you have a two-sided singly-linked list then it can look like
struct Node
{
int value;
struct Node *next;
};
struct List
{
struct Node *head;
struct Node *tail;
};
Two problems:
In store_via_ptr you allocate memory for i dynamically. When you use s_w_val you copy the structure, and then leave the pointer. Which means the pointer will be lost and can't be passed to free later.
In store_via_val you make swp->n point to the local variable j. A variable whose life-time will end when the function returns, leaving you with an invalid pointer.
The first problem might lead to a memory leak (something you never care about in your simple example problem).
The second problem is worse, since it will lead to undefined behavior when you dereference the pointer swp->n.
Unrelated to that, in the main function you don't need to allocate memory dynamically for the structures. You could just have defined them as plain structure objects and used the pointer-to operator & when calling the functions.
I created a global linked list. It doesnt work sometimes. First push is always succesfully done but second push makes error sometimes. I tried on another computer but its same.
typedef struct person{
char name[20];
char surname[20];
char musical_Work[20];
int age;
struct person *next;
}*top;
top head=NULL; /* GLOBAL */
void addNode( /* datas */ ){
top new_node=(top)malloc(sizeof(top));
/* copying datas */
new_node->next=head;
head=new_node;
}
The code top new_node=(top)malloc(sizeof(top)); allocates enough space for a top, which is a pointer to struct person. However, the space is going to be used to hold struct person, and therefore it must allocate enough space for struct person. Therefore, correct code for this is:
top new_node=(top)malloc(sizeof(struct person));
Additionally:
Using sizeof *new_node automatically allocates enough space for whatever new_node points to, even if the type of new_node is changed as the code is edited.
In C, there is no need to cast the type of malloc. This code can be top new_node = malloc(sizeof *new_node);.
Consider using a different name for a pointer to struct person, instead of top. It is not always the top of the stack.
I am approaching to use this code for building singly linked list. I am pointing out the lines which get me bit confused .
struct node
{
int data;
struct node *next;
}*start=NULL; // point 1
void creat()
{
char ch;
do
{
struct node *new_node,*current;
new_node=(struct node *)malloc(sizeof(struct node));
printf("\nEnter the data : ");
scanf("%d",&new_node->data); //point 2
new_node->next=NULL; // point 3
if(start==NULL)
{
start=new_node;
current=new_node;
}
else
{
current->next=new_node;
current=new_node;
}
printf("\nDo you want to creat another : ");
ch=getche();
}while(ch!='n');
}
point1: What is the advantage declaring the structure node as a pointer?
point2: scanf("%d",&new_node->data);
Not getting the idea how the data is stored here to the 'data' field in context of pointer and structure?
How Linked lists are different from arrays? Consider the following points :
An array is a static data structure. This means the length of array cannot be altered at run time. While, a linked list is a dynamic data structure.
In an array, all the elements are kept at consecutive memory locations while in a linked list the elements (or nodes) may be kept at any location but still connected to each other.
So considering the purpose of dynamic creation of linked list we do not know how many nodes user will create.
Therefore in this case to allocate memory dynamically, pointers are used.
Using pointers will give you the memory location
for your struct.
The purpose of scanf() is to accept the data and store it into the memory location. Here you are accepting an interger value for your data into struct which is named as new_node. So assume your new_node is something like:
new_node = {int data | struct node *next} Here you want to accept the value for your integer field data
There for the scanf will store what ever value you will type into the address location of new_node's data.
Here "1" represents your new_node->data accepted and "NULL" is
new_node->next the pointer to next node.
0a) pointers only save memory addresses, the compiler relies on your declaration to determine how much memory from that address (from *ptr to *ptr + size) is considered part of the object.
0b) within the struct node, you are saving the address of the 'next' node instead of saving the values of the 'next' node. this means at any time there's only one copy of each node.
1) }*start=NULL; is a short-hand way of declaring a struct node pointer called start with initialized value NULL, which means its pointing at nothing.
2a) Declaring pointers of type struct node lets the compiler know that after the pointer it can expect sizeof(struct node) amount of memory behind it to be readable. Obviously you have to malloc that memory beforehand otherwise errors will occur. Finally, the "ptr->data" is equivalent to "(*ptr).data", which dereferences the pointer and then asks for the data element of the struct node.
2b) the form of
int x;
scanf("%d",&x);
passes the &x(address of x) to the function, which reads an int and puts it AT address pointed to by &x. so &ptr->data is basically == address of data.
point1: What is the advantage declaring the structure node as a pointer?
You can use pointer to structure as function argument rather than structure itself so as to avoid making copy of struct. As when you pass a struct compiler makes a copy of that struct.
point2: scanf("%d",&new_node->data);
Arrow Operator(->) is used to access members of structures by pointer variable.
Here in above scanf statement new_node is the pointer variable which is accessing member data of the structure.
This operation is similar to the Dot Operator(.) where we access members of structure using ordinary structure variable.
This question already has answers here:
What is the reason for using a double pointer when adding a node in a linked list?
(15 answers)
Closed 9 years ago.
I have a question about signly linked lists in C. I've created a linked list with the code shown below :
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node* next;
};
struct node *mknode(int data)
{
struct node* np=malloc(sizeof(struct node));
np->data=data;
np->next=NULL;
return np;
}
struct node * insert (struct node* list,int data)
{
struct node *np;
struct node*curr=list;
struct node* prev=NULL;
np=mknode(data);
for(;curr &&data<curr->data;curr=curr->next )
prev=curr;
np->next=curr;
if(prev)
prev->next=np;
else
list=np;
return list;
}
int main()
{
struct node* head;
head=malloc(sizeof(struct node));
head=insert(head,7);
head=insert(head,2);
head=insert(head,4);
printf("%d",head->data);
printf("%d",head->next->data);
printf("%d",head->next->next->data);
return 0;
}
However,While I search on internet, I've realized that, the double pointer is used for creating linked list instead of a normal pointer.I mean, struct node **list , not struct node * list . I wonder why ? Which one is correct , and If both of them is true , what is the differences between them, I used my implementation with the sample main I wrote here, and it works fine but I dont know why should I use pointer to pointers ? Thanks in advance.
The reason some people use a pointer to a pointer is so that the nodes can be updated without returning a new pointer. In your example, if you wanted to change the head pointer, you would have to create a new pointer and then make head equal to that pointer. With the double pointer, you only have to free the space that the second pointer points to, and then update the second pointer to your new data structure, which keeps your original head pointer
I just use the single pointer in my implementations.
Read here, In this way you can change elements without creating new ones.
What is the reason for using a double pointer when adding a node in a linked list?
Given
struct node { int x; };
struct node **pplist;
struct node *plist;
pplist is a pointer to a pointer to a struct node, while plist is a pointer to a struct node. To change x, you would need to write
*pplist->x = 3;
plist->x = 4;
You would use a pointer to a pointer if you wanted the same variable to point to, say, different lists, or if you wanted to pass a pointer to a function with a side-effect of changing that pointer.
This looks perfectly fine to me.
All a pointer is, is a memory address to somewhere. A double pointer is just a memory address to another memory address which points to some data.
Maybe you can post where you saw node **list and we can explain it better but for now, your code looks good.
it is a bit of naturally, if you call "head = NULL; insert(&head, data);" that then head points to the first element. All functions, that supose to change the content, should be called indirectly.
BUT: this is a matter of coding convention. Some like it hot, some like it cold. The problem with head=insert(head, data); is, that head is unusable, when you forget "head="
Here is my data structure
struct Node{
int x;
Node *next;
Node *prev;
}
If I allocate memory
Node *A = malloc (sizeof (Node) * 10);
How can I access each box in the array using array index in this case? or it's not possible?
My goal just want to make a linked list in this chunk of memory.
basically i want to assign a block of memory and then assign their prev and next....
maybe it's confusing , sorry about my wording..
This gives you an array of 10 Nodes, accessible through A. Now, all you have to do is e.g.
A[0].next = &A[1];
to set the next value of the first node.
malloc returned void* then you should cast it for your type Node*
Node *A = (Node *)malloc (sizeof (Node) * 10);
Allocating many nodes the way you do may efficient for memory management but I wouldn't access them like an array. I think you should rely on the linked list and not mix the the two methods since it would easily lead to bugs hard to trace and evn harder to fix.