meaning of a struct within a struct in c [duplicate] - c

This question already has answers here:
What is self-referencing structure in C?
(3 answers)
Closed 3 years ago.
Can someone explain what we mean when we do, like what does struct Node* next do. does it create a pointer of type struct? any help and resources about structures in c would be helpful
struct Node {
int dest;
struct Node* next;
};

"struct" itself is not a type. "struct [tag]" is a type, for example "struct Node" in your code.
In your case you define a structure type. Every structure of that type will contain a pointer to another structure of that type as a member called "next".
This allows you to chain the structures together in a so called linked list. You store a pointer to the first structure in a variable, then you can follow the chain of links down to the structure you need.
For example, you can do
struct Node *start;
start = malloc(sizeof struct Node);
start->dest = 7;
start->next = malloc(sizeof struct Node);
start->next->dest = 13;
start->next->next = malloc(sizeof struct Node);
start->next->next->dest = 19;
printf("%d %d %d\n", start->dest, start->next->dest, start->next->next->dest);
free(start->next->next);
free(start->next);
free(start);
Please note that this code omits all error handling, in real code you have to handle the case when malloc returns NULL.
Also, in real code you would use such a structure in loops that traverse the chain, not directly as above.

As #Serge is pointing out in comments, is not a struct within a struct, is a reference (a pointer) to an object of the same type, an example:
#include <stdio.h>
struct Node {
int dest;
struct Node* next;
};
int main(void)
{
/* An array of nodes */
struct Node nodes[] = {
{1, &nodes[1]}, // next points to the next element
{2, &nodes[2]}, // next points to the next element
{3, NULL} // next points to null
};
/* A pointer to the first element of the array */
struct Node *node = nodes;
while (node) {
printf("%d\n", node->dest);
node = node->next; // node moves to the next element
}
return 0;
}
Output:
1
2
3
Of course, in my example there is no benefit in using a linked list, linked lists are useful when we don't know the number of elements before-hand.
Another example using dynamic memory:
struct Node *head, *node;
node = head = calloc(1, sizeof *node);
node->dest = 1;
while (more_elements_needed) {
node->next = calloc(1, sizeof *node);
node->next->dest = node->dest + 1;
node = node->next;
}
for (node = head; node != NULL; node = node->next) {
printf("%d\n", node->dest);
}

Related

C typecasting for structure pointers

Confused in some example with realization of trivial intrusive container in C.
I have structures:
struct List {
struct Link* first;
struct Link* last;
};
And Link for become the nodes of list:
struct Link {
struct Link* pre;
struct Link* suc;
};
Some pseudo Node for storing specified values in List:
struct Name {
struct Link lnk;
char* n;
};
Function for pushing values in List:
void push_back(struct List* lst, struct Link* p) {
assert(lst);
{
struct Link* last = lst->last;
if (last) {
p->pre = last;
last->suc = p;
}
else {
lst->first = p;
p->pre = 0;
}
lst->last = p;
p->suc = 0;
}
}
And usage of List:
int main() {
int count = 0;
struct List names;
struct Link* curr;
init(&names);
push_back(&names, (struct Link*)make_name("Norah"));
push_back(&names, (struct Link*)make_name("Annemarie"));
push_back(&names, (struct Link*)make_name("Kris"));
curr = names.first;
for (; curr != 0; curr = curr->suc) {
count++;
printf("element %d: %s\n", count, ((struct Name*)curr)->n);
}
return 0;
}
Question is, how typecast is working in this example? when sizeof(Link)==8 and sizeof(Name)==12
The pointer curr pointing to allocated memory for type Name, this structure not have suc and pre members,just lnk object of type Name (not pointer), and in code no any primary access for this member.
It is relying on the fact that struct Link is the first field of the struct Name. You can pretend the 12 bytes pointed to by a struct Name* is actually an 8 byte struct Link, and disregard the remaining 4 bytes. See the following questions:
Struct pointer compatibility
Is casting a struct T* to a struct C* undefined behavior, if T's first field is a C?
Does accessing the first field of a struct via a C cast violate strict aliasing?
Thanks guys! Im lost from mind that struct Link have two first members which each one 4 bytes. When struct Name is come to push_back() via argument, the function is operate with him like a struct Link.Cuz struct Name have 8 byte member in a head, functions just placing data about suc and pre members in this 8 bytes. I can replace lnk member from Name to any other with data with size 8 bytes.
Have i nice day!

listing doubly linked list items C

I'm new to C.I am trying to create a doubly linked list where the data field is a structure. But when I output the elements, only the first field of the structure is correctly displayed.
struct n
{
int a;
int b;
};
typedef struct _Node {
struct n *value;
struct _Node *next;
struct _Node *prev;
} Node;
typedef struct _DblLinkedList {
size_t size;
Node *head;
Node *tail;
} DblLinkedList;
DblLinkedList* createDblLinkedList() {
DblLinkedList *tmp = (DblLinkedList*) malloc(sizeof(DblLinkedList));
tmp->size = 0;
tmp->head = tmp->tail = NULL;
return tmp;
}
void pushBack(DblLinkedList *list, struct n *value) {
Node *tmp = (Node*) malloc(sizeof(Node));
if (tmp == NULL) {
exit(3);
}
tmp->value = value;
tmp->next = NULL;
tmp->prev = list->tail;
if (list->tail) {
list->tail->next = tmp;
}
list->tail = tmp;
if (list->head == NULL) {
list->head = tmp;
}
list->size++;
}
void printInt(struct n *value) {
printf("%d, %d", value->a, value->b);
}
void printDblLinkedList(DblLinkedList *list, void (*fun)(struct n*)) {
Node *tmp = list->head;
while (tmp) {
fun(tmp->value);
tmp = tmp->next;
printf("\n");
}
}
So, I have a few questions. Did I declare the node value field correctly? Am I inserting the node at the end of the list correctly? Am I doing the output of doubly linked list items correctly? And where is my mistake and how to fix it?
Did I declare the node value field correctly?
That depends on what your intention was. In terms of storing a pointer to a struct n: yes.
Am I inserting the node at the end of the list correctly?
Yes.
Am I doing the output of doubly linked list items correctly?
Yes.
And where is my mistake and how to fix it?
The code works from my point-of-view but what can be misleading is how pushBack operates. pushBack takes the struct n pointer as-is and stores it in Node. You did not post the pushBack caller code but the current implementation can caused problems if the caller assumes that the struct n gets copied.
To illustrate that, consider the following:
struct n value;
value.a = 1;
value.b = 2;
pushBack(list, &value);
value.a = 3;
value.b = 4;
pushBack(list, &value);
By reusing the value, two linked list nodes will effectively contain the same values. Also, the inserted struct n pointer must remain valid throughout the lifetime of the list. So, inserting stack-allocated values (that will be deallocated later by leaving their scope) or freeing dynamically-allocated values too early might lead to incorrect values. As long as the caller knows that, this is not necessarily a problem.
There are usually 3 ways to handle memory ownership:
Data structure owns values (just like it owns nodes) and is responsible for freeing them
Data structure copies values and is responsible for freeing them
Caller owns values and is responsible for freeing them
For a linked list, there's lots of merit in the strategy #3, because a linked list can be created from existing values without any copying or ownership transfer which would most certainly require changes to existing code. That's basically what your code is doing at the moment.

C: From char array to linked list

I'm still learning how to program in C and I've stumbled across a problem.
Using a char array, I need to create a linked list, but I don't know how to do it. I've searched online, but it seems very confusing. The char array is something like this char arr[3][2]={"1A","2B","3C"};
Have a look at this code below. It uses a Node struct and you can see how we iterate through the list, creating nodes, allocating memory, and adding them to the linked list. It is based of this GeeksForGeeks article, with a few modifications. I reccommend you compare the two to help understand what is going on.
#include <stdio.h>
#include <stdlib.h>
struct Node {
char value[2];
struct Node * next;
};
int main() {
char arr[3][2] = {"1A","2B","3C"};
struct Node * linked_list = NULL;
// Iterate over array
// We calculate the size of the array by using sizeof the whole array and dividing it by the sizeof the first element of the array
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
// We create a new node
struct Node * new_node = (struct Node *)malloc(sizeof(struct Node));
// Assign the value, you can't assign arrays so we do each char individually or use strcpy
new_node->value[0] = arr[i][0];
new_node->value[1] = arr[i][1];
// Set next node to NULL
new_node->next = NULL;
if (linked_list == NULL) {
// If the linked_list is empty, this is the first node, add it to the front
linked_list = new_node;
continue;
}
// Find the last node (where next is NULL) and set the next value to the newly created node
struct Node * last = linked_list;
while (last->next != NULL) {
last = last->next;
}
last->next = new_node;
}
// Iterate through our linked list printing each value
struct Node * pointer = linked_list;
while (pointer != NULL) {
printf("%s\n", pointer->value);
pointer = pointer->next;
}
return 0;
}
There are a few things the above code is missing, like checking if each malloc is successful, and freeing the allocated memory afterwards. This is only meant to give you something to build off of!

Testing a Linked List

I am reading Skiena's "The Algorithm Design Manual" for personal learning, and I am trying to implement the linked list in C.
How do I use the insert_list() function and then print out my list to verify the values?
/* definition of linked list */
typedef struct list {
int item;
struct list *next;
} list;
/* insert item into list */
void insert_list(list **l, int x) {
list *p;
p = malloc(sizeof(list));
p->item = x;
p->next = *l;
*l = p;
}
I wrote a main function to try and figure out how to use insert_list():
int main(void) {
struct list *root;
struct list *traverse;
root = (struct list *)malloc(sizeof(struct list));
root->next = 0;
root->item = 5;
traverse = root;
insert_list(traverse, 1); /* this is the problem */
printf("%d\n", root->item);
}
I receive an error at compilation with gcc:
expected 'struct list **' but argument is of type 'struct list *
How do I properly use this function to insert items into and then print my list? Without the insert_list() call, it prints root->item as 5, as expected.
You have a nice function. Now: use it.
int main(void) {
// You have a typedef, so you should omit the struct keyword
/*struct */ list *root= NULL, *p;
insert_list(&root, 5);
insert_list(&root, 1);
for (p=root; p; p=p->next){
printf("%d\n", p->item);
}
return 0;
}
As mentioned in the comments, the way to get it to compile is to change the call to insert_list() to this:
insert_list(&traverse, 1);
The insert_list() function takes a pointer to a pointer to a struct list, not just a pointer to a struct list.
You've written the code in an odd way. You're first assigning traverse to be equal to root and then calling the insert_list() function, which will overwrite traverse with the pointer to the new node it creates. At that point, the new node will be the "root" of your tree, not the root node you originally created. This will likely cause confusion when you attempt to traverse the list later.

How to make use of a structure pointer inside the structure itself

I am studying the following C code:
typedef struct msg *m_;
struct msg
{
long from;
long to;
m_ link;
};
m_ queue;
I would like to see an example that explains the role of the pointer, i.e. m_, of the structure inside the structure itself m_ link!
Thank you very much.
To be pedantic: link is a pointer. m_ is not a pointer, it's a typedef. It is used to avoid the need to say "struct msg* link;" inside the struct definition.
As answered in the comment above, the queue is represented by a pointer to the first item, which has a pointer to the second (if any), and so on until you reach a NULL pointer.
It's important to take care when building such lists that no node points to itself or to any precursor, or you get an infinite loop chasing to the tail.
Pointers to the structure type inside the structure itself are very often used for linked lists, trees, etc. In your example, it is referring to a queue implementation.
Here is a very minimal example of a stack implementation using a linked list. The functions require the address of a stack pointer, and an empty stack is a NULL pointer.
struct linked_stack
{
int data;
struct linked_stack *next;
};
void linked_stack_push(linked_stack **stck, int data)
{
struct linked_stack *node = malloc(sizeof(struct linked_stack));
if (node != NULL)
{
node->data = data;
node->next = *stck;
}
*stck = node;
}
int linked_stack_top(linked_stack **stck)
{
if (*stck != NULL)
return (*stck)->data;
return 0; /* stack is empty */
}
void linked_stack_pop(linked_stack **stck)
{
struct linked_stack *node = *stck;
if (*stck != NULL)
{
*stck = node->next;
free(node);
}
}
Example usage:
int main(void)
{
struct linked_stack *stack = NULL;
linked_stack_push(&stack, 10);
printf("top of stack = %d\n", linked_stack_top(&stack));
linked_stack_pop(&stack);
return 0;
}

Resources