I am new to C and thus still working on learning the language. I have created a linked list struct in a header file and I am trying to create a new instance of this struct. I know in java you can use the new operator but how would I mimic this behavior in c? Traditionally I would think of the following:
code within linked.h
typedef struct linked_list{
//assuming node type is implemented
node *next_node;
}
code within linked.c
linked_list *link = NULL;
link = malloc(number_nodes);
link->node_value = 10;
Any help you can provide is extremely helpful to me as I am having trouble understanding this concept.
malloc needs to know how many bytes to allocate, so you need to multiply the number of nodes by the size of one node in bytes.
Change:
link = malloc(number_nodes);
to
link = malloc(number_nodes * sizeof(*link));
Or if you just want a single struct:
link = malloc(sizeof(*link));
If you want enough memory for one struct linked_list, all you have to do is
struct linked_list * mylist = malloc(sizeof(*mylist));
mylist -> next_node = NULL;
For each node you want to add, you have to do
struct node * mynewnode = malloc(sizeof(*mynewnode));
mynewnode -> ... = ...; // fill in the data you have
mynewnode -> next_node = mylist -> next_node;
mylist -> next_node = mynewnode;
You should maintain the memory of all nodes independent on each other so you can free them.
Related
This question already has answers here:
Why use dynamic memory allocation(i.e. malloc()) when implementing linked list in c?
(6 answers)
Closed 2 years ago.
Below are separate codes for linked lists created using structure pointers and structure variables.
// Here a linked list is created using structure pointers
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node * ptr;
};
void traversal(struct Node * poin)
{
while(poin != NULL)
{
printf("%d, ", poin->data);
poin = poin->ptr;
}
}
int main()
{
struct Node * head = NULL; // Structure pointers
struct Node * second = NULL;
struct Node * third = NULL;
head = (struct Node *) malloc (sizeof(struct Node));
second = (struct Node *) malloc (sizeof(struct Node));
third = (struct Node *) malloc (sizeof(struct Node));
head->data = 5;
head->ptr = second;
second->data = 23;
second->ptr = third;
third->data = 839;
third->ptr = NULL;
traversal(&head);
return 0;
}
// Here the same linked list is created using structure variables
#include <stdio.h>
struct Node
{
int data;
struct Node * ptr;
};
// Pointer poin moves along different elements of a linked list
void traversal(struct Node * poin)
{
while(poin != NULL)
{
printf("%d, ", poin->data);
poin = poin->ptr;
}
}
int main()
{
struct Node head, second, third; // Structure variables
head.data = 5;
head.ptr = &second;
second.data = 23;
second.ptr = &third;
third.data = 839;
third.ptr = NULL;
traversal(&head);
return 0;
}
Why linked lists are created using structure pointers while the same can be done using structure variables, if we ignore the dynamic memory allocation? It is still confusing to me.
Linked lists are one of the "dynamic data structures", as oppopsed to static data structures like anykind of variables.
The main advantage (at least the advantage related to the "dynamic" attribute) is the possibility to change the total of the data structure at runtime. The focus is on the structure, not on the values inside the structure.
For your question, the most relevant kind of change at runtime is increasing the number of elements, i.e. adding more of them, especially adding a number of additional elements which cannot be predicted at before runtime. (I should specify runtime as the time when the program is already busy doing its job, i.e. after setting up variables.)
If you use variables (even arrays, even variable length arrrays after they have been initially created) the number is fixed. You can setup a large number, large enough for the maximum of needed elements. But if you cannot determine such a maximum you are in a dead end.
TLDR
Dynamic data structures can grow (and shrink and grow again) during runtime.
Variables cannot.
So I reject your "the same can be done using structure variables".
(This answer focuses on C, which you have tagged. For other languages, including C++, more aspects would have to be discussed.)
I'm attempting to refactor some code, to reduce duplication.
This is a curated example, currently defined in each .c file.
struct hrentry_t
{
int custom1;
int custom2;
int custom3;
struct hrentry_t *prev, *next;
};
struct hrentry_t*
attachentry(struct hrentry_t* hentry)
{
struct hrentry_t* hnew = calloc(sizeof(struct hrentry_t), 1);
if (hnew == NULL)
return NULL;
if (hentry != NULL) {
while (hentry->next != NULL) {
hentry = hentry->next;
};
hentry->next = hnew;
hnew->prev = hentry;
}
return hnew;
}
https://github.com/techzilla/check_snmp_extras, is the entire codebase.
I'm declaring and initializing a custom double linked list, and corresponding allocate function. If I moved the linked list functions and code to the common lib .c and .h, how can I get the file specific data inside of each list entry? Each file requires different types and number of variables.
Maybe I make a the double linked list contain only prev next and data? Then somehow make data a handle to an incomplete struct? How would then that need to be allocated though? I'm open to fully reconsidering my approach, so solid advice from experienced coders is always appreciated.
One approach is to make your specialized list data types castable to a generic double-linked list structure. This can be accomplished by putting the non-specialized data members at the beginning of the structure:
struct node_t {
struct node_t * prev, * next;
};
struct hrentry_t
{
struct node_t node;
int custom1;
int custom2;
int custom3;
};
It then makes sense to cast an hentry_t* to a node_t*. The signature of your attachment function becomes:
struct node_t* attachentry(struct node_t* node);
And to use it, you cast instances of your specialized type to the generic type:
struct hentry_t * my_hentry_ptr; /* initialized somehow... */
my_list = attachentry((struct node_t*)my_hentry_ptr);
you are returning hnew if there is already a linked list present rather than the previous list with hnew added onto the tail of it.
return hrentry;
try this
I have to create a struct for a map in C that contains a char* key and void* value which are stored together internally. Rather than having a linked list as an external struct, I have to allocate memory for a linked list cell which contains the link pointer, the key string, and the value together (contiguous).
The key and value data have to be stored directly in the cell and the cell has to be constructed at runtime. I get the beginning of this which would involve a struct like:
struct example {
int count_of_list_elem;
void *list;
}
But I don't know how this is possible w/o using another struct to form the linked list?
Would I have to create some cell within the struct itself, allocate memory to it and pass it three values? I'm just not sure how it would work.
EDIT: I need to use a void* array.
This is a standard way of handling dynamically sized structures in C:
struct example {
struct example *next; /* linked list */
int count_of_list_elem;
char data[1];
}
struct example *bigone = malloc (sizeof (struct example) + 10000);
if (!bigone)
// error
bigone -> next = NULL;
bigone -> count_of_list_elem = 10000;
memcpy (bigone -> data, <data source>);
You can declare a struct before you define it, so that you can refer to it within the struct itself:
typedef struct tagMyStruct* my_struct_pointer;
typedef struct tagMyStruct
{
char* KeyPtr;
void* ValuePtr;
my_struct_pointer NextPtr;
} my_struct;
static my_struct_pointer _listHeadPtr = NULL;
my_struct_pointer AddNewCellToList(char* keyPtr, void* valuePtr)
{
my_struct_pointer newCellPtr = malloc(sizeof(my_struct));
newCellPtr->KeyPtr = keyPtr;
newCellPtr->ValuePtr = valuePtr;
newCellPtr->NextPtr = _listHeadPtr;
_listHeadPtr = newCellPtr;
return(newCellPtr);
}
You will need to malloc appropriate storage for the Key and Value before calling AddNewCellToList.
You can refer to a struct type within its own definition:
struct example {
int count_of_list_elem;
void *list;
struct example *next;
}
Your handle on the whole linked list is just a pointer to the first element:
struct example *head;
You will want to be careful when you create a new node to initialize its next pointer to NULL to indicate that there are (initially) no elements after it.
I am trying to dynamically allocate list of pointers to pointers of structs which each contain a list of structs with the following definition:
struct node {
char *text;
struct node *next; };
I am also using a typedef:
typedef struct node Node;
I am creating a list of nodes to hold each list by declaring the following:
Node **list;
list = (struct node**) malloc(sizeof(struct node*) * arraySize);
At each of the nodes of list I will have another list which I am creating as follows:
list[i] = malloc(sizeof(struct node*) * subArraySize);
I have several questions:
Is this the correct implementation for such a problem?
How can I access the text data member of the first node of each list within the larger list?
If my question is vague please let me know. My confusion on this topic makes it difficult to word my question properly.
Assuming your memory is allocated and filled up correctly, you'd access the text data member of the first node of each node* array within the larger node** array via:
list[i]->text
But, to answer your question about the implementation being correct, it's not really. You'd probably be happier doing this:
struct node **list;
list = (struct node**) calloc(sizeof(struct node*) * arraySize);
for (int i=0; i<arraySize; ++i) {
list[i] = (struct node*) malloc(sizeof(struct node));
list[i]->text = ""; // or whatever you want to start with
list[i]->next = NULL;
}
This creates a node** array (called list, since you wanted to call it that, but I would call it something else indicates it's an array of node-based linked lists), then instantiates a block of memory for each head node so that list is full of valid node*s and you can start working with them.
When you go to append something to each of your linked lists, you'd do something like this (this appends to the end, it's up to you to implement insertion based on comparing values if you want sorted data, etc.):
int i = index_where_you_want_to_insert;
struct node *currNode = list[i];
struct node *newNode = (struct node*) malloc(sizeof(struct node));
newNode->text = ""; // or whatever you want to start with
newNode->next = NULL;
while(currNode->next != NULL) {
currNode = currNode->next;
}
currNode->next = newNode;
It may also help you to see this question about using typedef with linked lists.
If I've made any syntactic or semantic errors in my code, I apologize, it's been a while since I wrote C and I may be rusty with how to refer to structs. I welcome corrections.
I'm having trouble understanding a piece of C code that represents a linked list structure. The skeleton of the struct looks like this:
struct r{
r *next;
r **prev;
data *d;
}
struct r *rlist;
rlist can be filled by calling the following function: (skeleton only)
r* rcreate(data *d){
struct r *a = xmalloc(sizeof(*r))
a->d = d;
a->next = rlist;
a->prev = &rlist;
if (rlist)
rlist->prev = &a->next;
rlist = a;
return a;
}
How do I go about using this data structure? e.g. how to traverse rlist ?
Edit: here is the function for deleting a node in the linked list
void rdestroy(struct r *a){
if (a->next){
a->next->prev = a->prev;
}
*a->prev = a->next;
destroy(a->d); /* destroy is defined elsewhere */
}
Double prev pointer seems to allow traversing list in one direction only, while allowing easy deletion (because even though you can't access the previous element (easily), you can access the next pointer of previous element, and set it to new correct value when deleting a node.
Without seeing other related functions, it's hard to see why it is done this way. I've not seen this done, and can't immediately think of any really useful benefit.
I think this allows having simpler node deletion code, because node does not need to care if it first or not, because node's prev pointer will always have non-NULL value to a pointer it needs to modify when deleting itself. And same simplicity for insertion before a current node. If these operations are what dominate the use pattern, then this could be seen as minor optimization, I suppose, especially in older CPUs where branches might have been much more expensive.
How to traverse list
This was the question, right? You can only traverse it forward, in a very simple manner, here's a for loop to traverse entire list:
struct r *node;
for (node = rlist ; node ; node = node->next) {
// assert that prev points to pointer, which should point to this node
assert(*(node->prev) == node);
// use node
printf("node at %p with data at %p\n", node, node->d);
}
Example insertion function
This example insertion function demonstrates how insertion before a node needs no branches (untested):
struct r *rinsert(struct r *nextnode, data *d) {
// create and initialize new node
struct r *newnode = xmalloc(sizeof(struct r));
newnode->d = d;
newnode->next = nextnode;
newnode->prev = nextnode->prev;
// set next pointer of preceding node (or rlist) to point to newnode
*(newnode->prev) = newnode;
// set prev pointer of nextnode to point to next pointer of newnode
nextnode->prev = &(newnode->next);
return newnode;
}
There's no good reason to have r ** next in that structure. It's for a double linked list.
So if this thing is created you have it assigned
thisList = rcreate("my data")
now you could start with traversing it
while (thisList->next)
thisList = thisList->next.
...
Your code has many syntactical errors in it, probably because (as you say) it is a "skeleton," so it is hard to parse what the author (whether it was you or someone else) actually intended this code to do.
A simple (doubly) linked list structure looks like this:
struct node {
struct node *next, *prev; // pointers to the adjacent list entries
int data; // use whatever datatype you want
};
struct node *list = NULL; // the list starts empty
void add_entry(int new_data) {
struct node *new_entry = malloc(sizeof(struct node));
// note that in the above line you need sizeof the whole struct, not a pointer
new_entry->data = new_data;
new_entry->next = list; // will be added to the beginning of the list
new_entry->prev = NULL; // no entries currently front of this one
// in general a NULL pointer denotes an end (front or back) of the list
list->prev = new_entry;
list = new_entry; // now list points to this entry
// also, this entry's "next" pointer points to what used to
// be the start of the list
}
Edit: I'll say that if you want us to help you understand some code that is part of a larger program, that you did not write and can't modify, then please post the relevant code in a format that is at least syntactical. As others have said, for example, the use of prev in the code you posted is indecipherable, and it isn't clear (because there are other similarly confusing syntactical problems) whether that was in the original code or whether it is an error introduced in transcription.
Yang, I am not sure how comfortable you are with pointers in general. I suggest taking a look at few other linked-list implementations, it might just do the trick.
Take at look at this Generic Linked List Implementation.