Define a struct with a member pointing to another member - c

I'm trying to program a network in C. I have nodes which are linked to each other and I 'd like to do that by making the struct member point to another member (not to another node, because I want to preserve the identity of the links).
The code I made to do that is something like:
struct node{
int k; //number of links
struct node.link **link; //<- wrong
};
but this is not right as node is not a variable but a type of variable (this is already discussed as an error in another QA: first you have to define a variable of node type and then apply the .link, but this doesn't help here). There's also a QA called "Struct member point at another struct member" but they don't do it from definition and it is not so clear how to generalize it (at least for me).
Is it a correct way to do this?

The problem is that the C language doesn't let you create the type you want. You need a type T with the property *T has the same type as T. You can't do that. (Well, function pointers have that property, but that's an irrelevant technicality.)
You have to introduce a new name. C only lets you do this with structs or similar constructions.
struct link {
struct link *ptr;
};
struct node {
int k;
struct link *link;
};
This will get you what you want. Now, in order to go from a struct link * to a struct node *, you'll have to do some pointer math:
struct node *node_from_link(struct link *link) {
return (struct node *) ((char *) link - offsetof(struct node, link));
}
This is also provided by the container_of macro, which is not part of the C standard, but you can find a definition for it online.
Or, you could just go the traditional route.
// Usually easier to do it this way...
struct node {
int k;
struct node *link;
};

Is this what you are after?
struct Node
{
int k; //number of links
void* link;
};
struct Node* create()
{
struct Node* node = malloc(sizeof(struct Node));
node->k = 0;
node->link = 0;
return node;
}
void link(struct Node* from, struct Node* to)
{
from->link = &(to->link);
}
int main()
{
struct Node* child = create();
struct Node* parent = create();
link(parent, child);
return 0;
}
I've used void* for the link for the reason expressed by Dietrich: you want a pointer to the link to be the same type as the link. This effectively means a cast, so why not just use a generic pointer?

Membership in a structure, generalized or specific, is not an attribute of C data types. There is therefore no way to declare a pointer that can only point to a structure member, and not to any other variable of compatible type.
On the other hand, you don't need to do anything special to declare a pointer that can point to a member of another structure. You just need a pointer to that member's data type, and structure membership is irrelevant to that data type.
For example, you can have
struct node {
int k; /* number of links */
struct node **links; /* points to a dynamic array of node pointers */
struct node **one_link; /* points to a node pointer from another node */
};
In that case, it might make sense to do something like this:
struct node *n1 = /* ... */;
struct node *n2 = /* ... */;
n2->one_link = &(n1->links[3]);
Overall, though, I think this is kind of convoluted. There is probably a better way to structure your data.
Update:
Based on your description of what you're after:
[...] links are bidirectional, if I destroy one link (say the one that links node 1 to node 3) I'll need to destroy the node 1 link AND the corresponding link from node 3. Then I need to know more than just who is link to who. I need to know which link they are using.
there are at least two possible solutions, depending on details of how your nodes are structured. If they are structured like I show above, with an array (dynamic or not) of pointers to other nodes, then your general idea simply won't work. That's because the position of each link within an array of links will change as you delete other links (supposing that you close the gaps). Instead, you can just scan:
struct node {
int k; /* number of links */
struct node **links; /* points to a dynamic array of node pointers */
struct node *parent; /* points to a node that links to this one */
};
void delete_node(struct node *n) {
if (n->parent) {
int i;
for (i = 0; i < n->parent->k; i += 1) {
if (n->parent->links[i] == n) {
/* ... delete the ith element of n->parent->links ... */
break;
}
}
}
/* ... clean up node n ... */
}
If one node's links to others are stored in separate members, on the other hand, then you could indeed provide a double-pointer by which to remove links from the parent, but the presence of member k in your original structure tells me that's not your situation.

Ok, this is how I finally solved it in my program:
typedef struct node{
int k; //connectivity
struct link **enlace; //vector of LINKs
}NODE;
typedef struct link{
NODE *node1;
NODE *node2;
}LINK;
Basicly, I defined two structures: one is the NODE type, which contains the information of how connected is the node and a vector of LINKs, and the other is the structure LINK which contains the information of the link itself, I mean which nodes the link connects.
With these two I'm able to create the network of nodes with a connectivity following a Poisson distribution, and then destroy each link one by one, choosing one link at random from a list and then redirecting the pointers of each node to NULL.

Related

how to fix "invalid use of undefined type" of struct type in C?

Sorry first for my bad English. I'm begginer in C, trying to make a Singly Linked List.
This is my setup of the List:
#include <stdio.h>
#include <stdlib.h>
typedef int Element;
struct
{
Element Data;
struct Node *Next;
} Node;
typedef struct Node *Position;
typedef Position List;
This is how I initialize this Struct (i dont know if this function is wrong):
void resetList(List *L)
{
*L = (struct Node *)malloc(sizeof(Node));
};
My problem is, wherever I used the (->), I will got this error
error: invalid use of undefined type ...
the compiler mark the error at any (->) in my code. For example:
int isEmpty(List L)
{
return (L->Next == 0);
};
will get the error at (->).
I know my code is so dump. Please help me. Thanks.
My problem is, wherever I used the (->), I will got this error
Your struct needs to be defined as a type and at the same time a self-referencing type, able to point at a variable which is of the same type as itself. In can be done like this:
typedef struct Node
{
Element Data;
struct Node *Next;
} Node;
Where the first Node is a struct tag, which is a name allowed to co-exist with the type name Node later defined at the } Node;.
Hiding pointers behind a typdef like typedef struct Node *Position; is horrible practice, because it achieves nothing except making the code much harder to read for everyone including yourself. There's no need for a typedef at all here, just declare a variable Node* Position.
Similarly, drop the typedef Position List;, creating new types just for the heck of it only creates clutter.
This is how I initialize this Struct (i dont know if this function is wrong):
The reason why you aren't sure, is because of all the obscure typedefs. Consider rewriting the function as:
void resetList (Node** list)
{
*list = malloc(sizeof(Node));
};
The reason why it has to be a pointer-to-pointer is explained here: Dynamic memory access only works inside function
As for what this function does, resetList is a very weird name for a function allocating a single node. I would expect it to delete the previous list if present and then maybe allocate a new node.
In general, the first declaration of struct Node is not correct. If you specify the name of the structure at the end of its declaration, you are not specifying data type, but you create only the struct variable. Therefore, the compiler doesn't know how to allocate struct Node *Next; item in your struct.
You can simply repair your code by moving the name of the structure:
typedef int Element;
struct Node
{
Element Data;
struct Node *Next;
};
typedef struct Node* Position;
typedef Position List;

What is meant by struct node *next; in a linked list program made in c language?

// Linked list implementation in C
#include <stdio.h>
#include <stdlib.h>
// Creating a node
struct node {
int value;
struct node *next; //What is this, what are we doing here?
};
// print the linked list value
void printLinkedlist(struct node *p) {
while (p != NULL) {
printf("%d ", p->value);
p = p->next;
}
}
int main() {
// Initialize nodes
struct node *head;
struct node *one = NULL;
struct node *two = NULL;
struct node *three = NULL;
// Allocate memory
one = malloc(sizeof(struct node));
two = malloc(sizeof(struct node));
three = malloc(sizeof(struct node));
// Assign value values
one->value = 1;
two->value = 2;
three->value = 3;
// Connect nodes
one->next = two;
two->next = three;
three->next = NULL;
// printing node-value
head = one;
printLinkedlist(head);
}
I want to ask what are we doing here with this line of code?
it's in the creating a node part of the code (top).
struct node *next;
Are we assigning a pointer type struct variable for the sturct node but its inside of the same struct, assigning a variable named *next inside the same struct? But that isn't allowed, right?
we can either declare the variable out side the } and between ; or in the main()
function part of the code only, Isn't it?
Like
main()
{
struct node *next;
}
Again, then I came across a post mentioning it as a pointer to the structure itself, can anyone explaine how can we do this inside the same struct?
The next member points to another instance of struct node. Graphically, we usually represent it like this:
+–––––––+––––––+ +–––––––+––––––+
| value | next |––––> | value | next |
+–––––––+––––––+ +–––––––+––––––+
A struct type cannot contain an instance of itself - we can’t create a type like
struct node {
int value;
struct node next;
};
for two reasons:
The type definition isn’t complete until the closing }, and you cannot create an instance of an incomplete type;
The type would require infinite storage (struct node contains a member next of type struct node which contains a member next of type struct node which contains a member next of type struct node...);
However, we can declare next as a pointer to struct node, since we can create pointers to incomplete types. The size and representation of a pointer is independent of the size and representation of the type it points to.
What it means
The line struct node *next; is read as "next is a pointer to another struct node".
This is just a recursive structure declaration (definition):
struct node {
int value;
struct node *next; //What is this, what are we doing here?
};
It says a node consist of two parts:
an integer value
a pointer to another node.
The wiki article on linked lists has a nice visualization showing how one node points to another (or to NULL to end the chain).
How does it work?
As you noted, the interesting part is how the declaration can include a reference back to itself. The compiler handles this in two steps:
It sizes the struct as consisting of an int and a pointer (they're all the same size regardless of what they are pointing to).
Later it type checks the assignment and generates the appropriate assembly. When you write one->value = 1;, it makes sure the 1 is an integer and generates code to move 1 to the integer slot. And when your write one->next = two;, it verified that two is a pointer to a node and generates code to move that pointer to the second slot for the struct node pointer.

Is it possible to write a generic traverse function in C for different list structures so long as they contain the "next" field?

First time asking a question but I did look around Google and stackoverflow to see if someone has asked something similar before. In malloc, recasting and free, it looked like the OP asked something similar for example. But it was more complicated.
I was wondering whether it's possible to create a generic function for a list structure in C that traverses the list given that you know that the different types of structures will always have a "next" field.
For example, given these two list-type structures:
typedef struct _list1 {
int value;
list1 *next;
} list1;
typedef struct _list2 {
int value;
char *string;
list2 *next;
} list2;
Is it possible to create a generic void freeList((void *) list) function or something which looks something like the below? I am aware it's a simple thing to write both free functions for each individual list separately.
void freeList((void *) list) {
// Included this because the structs would have different sizes
// so I thought it would be possible to cast it in order to properly dereference the field.
if (sizeof *list == sizeof list1)
*list = (list1) list;
else if (sizeof *list == sizeof list2)
*list = (list2) list;
if (!list) return;
else {
free(list->next);
free(list);
}
}
So far, my experiments with the code shown above didn't fare well given that gcc would complain about dereferencing a void * pointer.
Making a heterogeneous list can be achieved by the use of a tagged union, or just a tag and casting:
struct list_item {
struct list_item *next;
enum datatype type;
void *contents;
};
or
struct list_item {
struct list_item *next;
enum datatype type;
union {
int some_int;
char some_char;
} contents;
};
Then while traversing the list you just have to verify the type stored in type before using the contents of the element.
This check:
if (sizeof *list == sizeof list1)
*list = (list1) list;
else if (sizeof *list == sizeof list2)
*list = (list2) list;
doesn't work because sizeof is a static construct: its value is defined at compilation time. You're just asking for the sizeof void.
is it possible to create a generic function for a list structure in C that traverses the list given that you know that the different types of structures will always have a "next" field.
Yes, as mentioned before; you must be careful that every structure starts with the "next" field; the two structures in your post should therefore be reordered like this:
typedef struct _list1 {
list1 *next;
int value;
} list1;
typedef struct _list2 {
list2 *next;
int value;
char *string;
} list2;
It is not clean code, because the compiler could reorder (and pad) the fields of the structure, but in general it should work.
Is it possible to create a generic void freeList((void) *list) function or something which looks something like...
This is possible if your structs do not refer malloced memory; or they do, but in a uniform (and known) way (note the first case is a sub-case of this last).
If the structs contain pointers pointing to memory that has to be freed, in fact, while freeing the struct the freeList() function should also free the referenced memory. A few solutions come to my mind:
1 - If all the different structs contain the same "pointers" layout, the routine can free those pointers in a uniform manner, knowing in advance what to do. In such scenario, one can also use pointer fields that are not used by all the structs, but only some.
2 - Every single instance of a struct could contain some helper field describing the pointer's layout. For example, just after the "next" field, another "mempntcnt" field could tell how many pointers (to be freed) follow the "next" field. Or, this "mempntcnt" could be passed as a parameter to freeList().
3 - This problem could be managed by a totally separated mechanism, outside the scope of freeList(). Much depends on the final usage: I mean, for a given (kind of) linked list, first call a routine that frees all the memory referenced by the list itself, then free the list by calling the common freeList(). After all, if different structs are needed, then different routines are used on them...
I hope I've been clear enough...
If you ensure that the next pointer is the first member of the struct then this is possible.
typedef struct list1 {
// next pointer must be first
struct list1 *next;
int value;
} list1;
typedef struct list2 {
// next pointer must be first
struct list2 *next;
int value;
char *string;
} list2;
void freeList(void *list) {
if (list) {
freeList(*(void**)list);
free(list);
}
}

Linked-list is confusing

I am stuck, as I don't understand what is this code doing:
struct node
{
int info; /* This is the value or the data
in the node, as I understand */
struct node *next; /* This looks like a pointer. But
what is it doing in real life? */
} *last; /* What is this and why is it
outside the body? What is this
thing doing? */
I know that when a node is created, it has a value, and it is pointing to some other node
but I don't understand the syntax.
Is this a better way of writing the code above?
Is there a simpler way of writing the same struct for better understanding?
In my lectures they presume that the student has understanding of what they teach.
Well, we can explain this to you, but we can't understand it for you.
Code snippet you've provided is definition of variable last, being pointer to newly defined structure type node. It can be written other way as:
typedef struct _node_t {
int info;
node_t *next;
} node_t;
node_t *last;
This way we define typedef, which is, say, alias of type definition to some short name — in this particular case, it aliases structure of two fields as the name node_t. Wherever you define something as being of type node_t, you tell compiler that you mean 'this should be aforementioned structure of two fields', and node_t *last means 'variable last should be pointer to node_t type'.
So, back to syntax:
struct foo {
int a;
float b;
void *c;
} bar, *baz;
means 'Define structure type foo, and make it contain three fields — integer a, float-point b and untyped pointer c, then make variable bar to be of this structure type, and make variable baz to point to this structure type'.
Now to pointer. What you see is called 'recursive definition', e.g. type mentions itself in it's own definition. They are okay, if language supports them (C does), but one could avoid recursive definitions in linked list node structure by specifying next node pointer to be just untyped:
struct node_t {
int info;
void *next;
};
This way you no longer reference node_t type from node_t type, but that adds you some inconveniences when using this type (you have to explicitly cast next to node_t type, like ((*node_t)(last->next))->info instead of just last->next->info).
If you feel you need additional reference, consider taking a look at interactive online tutorials, like http://www.learn-c.org/ (I'm not affiliated).
that is the simplest way to write a linked list node , but why name it last ? name it node instead , this makes it more understandable , but here's how it works.
when a linked list is first created it contains only the root node (the first node in a linked list) , when you add a node , you fill the info field with the data that node will hold (note that info may be any kind of data , character , string , int ...) then set next to NULL , since that node is the last node in the list.
when you add another node , you change the value of next to point to the node you just added and you set the value of next to NULL in the node you just created because now that is the last node in the list .
you can repeat this to add as many nodes as your memory allow you to.
this link may help you to better understand structures
typedef struct marks {
int m;
struct marks *next;
} marks_t;
This way we define a structure so that a Linked List can be formed. Now we have defined the last variable next as a "structure pointer" which gives us the address of the next element in the list (i.e. as structure only)!
The last element does not point to any node (here marks structure) and hence the pointer variable has NULL value.
Now to define the first element:
marks_t *list;
if (list == NULL) {
list = (marks_t *) malloc(sizeof(marks_t));
}
list->m = 15;
list->next = NULL;
Now if we want to add an element next to this (i.e. second element):
marks_t *next1;
next1 = (marks_t *) malloc(sizeof(marks_t));
next1->m = 27;
next1->next = NULL;
list->next = next1; // Storing address of next1 structure in list

How to use a struct in C?

This is code for a linked list in the C programming language.
#include <stdio.h> /* For printf */
#include <stdlib.h> /* For malloc */
typedef struct node {
int data;
struct node *next; /* Pointer to next element in list */
} LLIST;
LLIST *list_add(LLIST **p, int i);
void list_remove(LLIST **p);
LLIST **list_search(LLIST **n, int i);
void list_print(LLIST *n);
The code is not completed, but I think it's enough for my question. Here at the end of struct node "LLIST" is used, and it's also used as a return type in the prototyping of the function list_add. What is going on?
That's a typedef. It's actually doing two things at once. First, it defines a structure:
struct node {
int data;
struct node *next;
}
And then does a typedef:
typedef struct node LLIST;
That means LLIST is a type, just like int or FILE or char, that is a shorthand for struct node, your linked-list node structure. It's not necessary - you could replace LLIST with struct node in all of those spots - but it makes it a bit easier to read, and helps hide the implementation from pesky end-users.
LLIST is just another type name for the struct that has been created. In general, the following format will create a type "NAME" that is a "struct x":
typedef struct x { ... } NAME;
C requires that you reference structs with a "struct" prefix, so it's common to introduce a typedef for less verbose mention.
That is, the declaration of your struct has two parts, and can be rewritten as such:
struct node {
int data;
struct node *next; /* pointer to next element in list */
};
typedef struct node LLIST;
So, LLIST is just another name for struct node (thanks Chris Lutz).
typedef creates a new "type" in your program, so the return value and types of parameters of those functions are just your struct. It is just shorthand for using struct node for the type.
If you were to create a new node, you could do it like this (using the type):
LLIST *node = malloc(sizeof(LLIST));
node->data = 4;
node->next = someOtherItem;
list_add(node, 1)
Also, with the function prototypes in your question, you don't really need the double pointers; since the data in your struct is just an int, you could do something like
LLIST *list_add(int data, int position);
then the list_add function would handle the allocation, copy the int into the struct and add it to the linked list.
Putting it in at a certain position is as simple as changing the next pointer in the node before it to the address of the newly allocated node, and the next pointer in the new node to point at the next one (the one the node before that one was originally pointing at).
Keep in mind that (given the rest of your function prototypes) you will have to keep track of pointers to every node you create in order to delete them all.
I'm not sure I understand how the search function will work. This whole thing could be implemented a lot better. You shouldn't have to provide the location of a node when you create it (what if you specify a higher number than there are nodes?), etc.
LLIST* is a pointer to a structure defined by the LLIST struct.
You should do
LLIST* myList = malloc(sizeof(LLIST)*number_of_elements);
to have some memory allocated for this list. Adding and removing items requires you to reallocate the memory using realloc. I've already written some piece of code for lists (made with arrays).
I might post the code as soon as I'm home, which is currently not the case.

Resources