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!
Related
I've been learning C for a month now and I've learned/remember that functions are defined like this:
return_type function_name( parameter list ) {
...body
}
But in a lecture about 'list ADTs' the example code which illustrates making and printing a full list there were some pieces of code(function declarations) in a form that I've never seen.
...
typedef struct list{ int data; struct list *next; } list;
list* create_list(int d) {
...
}
To my understanding the return type is ' list '(?) which is a structure tag, and the function name is ' * create_list ' (which is a dereferenced pointer??). I couldn't understand why it was written like that. I want to know how it works and how to use it. How does it differ from other (normal looking)functions like struct create_list(int d) {...}? The instructor didn't mention or explain about these so I'm quite confused.
here is the full code just in case
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
typedef struct list{ int data; struct list *next;} list;
int is_empty(const list *l) { return (l == NULL); }
list* create_list(int d) {
list* head = malloc(sizeof(list));
head -> data = d;
head -> next = NULL;
return head;
}
list* add_to_front(int d, list* h) {
list* head = create_list(d);
head -> next = h;
return head;
}
list* array_to_list(int d[], int size) {
list* head = create_list(d[0]);
int i;
for(i = 1; i < size; i++) {
head = add_to_front(d[i], head);
}
return head;
}
void print_list(list *h, char *title) {
printf("%s\n", title);
while (h != NULL) {
printf ("%d :", h -> data);
h = h -> next;
}
}
int main() {
list list_of_int;
list* head = NULL;
int data[6] = {2,3,5,7,8,9};
head = array_to_list(data, 6);
print_list(head, "single element list");
printf("\n\n");
return 0;
}
any help would be appreciated!
Please correct me if I'm wrong in some point. Thank you
You're close, but reading it wrong. Function names do not have things like * in them, only types do.
This defines a function that returns list* (a.k.a. struct list* which is what typedef establishes earlier) given argument d of type int:
list* create_list(int d) {
// ...
}
In other words, create_list returns a pointer to list. In a type definition * means pointer, but it has a different meaning as an operator, such as:
int x = 0;
int* y = &x;
*y = 5; // Dereference y pointer, make assignment, in other words, assign to x
You can usually spot a dereference operator because it is not part of a type either in a return type specifier, an argument, or a variable declaration. In most other cases it's the dereference operator.
To my understanding the return type is ' list '(?) which is a structure tag
In your example list is both a struct tag and a typedef name. The name space rules of C allow four different categories of identifiers:
lables (for goto etc)
struct/union/enum tags (struct this_is_a_tag).
struct/union members
everything else
It's valid to name identifiers from these different name spaces the same.
In the example
typedef struct list{ int data; struct list *next;} list;
the typedef list identifier isn't available until at the end of the declaration (after the ;). The struct tag struct list is, however. So the struct list *next; member refers to the struct tag, which is a convenient way create a self-referencing struct. Once the typedef is declared, we can either use list to refer to the typedef:ed struct type, or we can use struct list which means the very same thing - when used outside the struct declaration it's just a style preference which form to use.
So list* create_list(int d) is using the typedef list to declare the return type of the function as a pointer to struct, list*. No different from returning any variable by value vs returning a pointer to it.
In this case the function is calling malloc to create a struct variable, so the function needs to return a pointer because anything allocated by malloc is always accessed through pointers.
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);
}
I'm trying to create a singly linked list without implementation. I'm doing this just to gain some deeper understanding on how structures work. I just want to create 2 nodes in the main function and link them. I could do that using typedef in the declaration of structures and by making the implementation, but that's not what I want (I can do that successfully).
I've written some code, but an error occurs at line 27 (the same problem appears at lines 29, 30 and 33). I know the explanation for this problem is rather simple, but I couldn't find it, either on my mind or on the web (or books). I'd appreciate any assistance in this problem. I've been programming just for the last year.
I thought in asking for help in CodeReview, but accordingly, to their FAQ, that wasn't the place to ask for help with this kind of problem.
Errors are:
27:11: error: incompatible types when assigning to type 'struct NODO ' from type 'struct NODO'
E.sig = F;
Same problem with the other lines. Everything is in the same file (.c).
Here's the full code:
#include <stdio.h>
#include <stdlib.h>
struct NODE {
int data;
struct NODE *next;
};
struct LIST {
struct NODE *first;
struct NODE *last;
int size;
};
void main(){
struct NODE E;
struct NODE F;
struct LIST L;
E.data = 1;
E.next = NULL;
F.data = 2;
F.next = NULL;
E.next = F; // line 27
L.first = E; // line 29
L.last = F; // line 30
struct NODE *ptr;
ptr = E; // line 33
while(ptr != NULL){
printf("%i\n", ptr->data);
ptr = ptr->next;
}
}
The problem is that you are trying to assign an object to a pointer. You should assign the address of your node and note the node object itself.
Try E.next = &F; and same for all the others.
A pointer is a variable whose value is the address of another variable, i.e., direct address of the memory location. So you have to provide the address of the memory location .In C address of a variable is derived using & operator.
Modified code :-
#include <stdio.h>
#include <stdlib.h>
struct NODE {
int data;
struct NODE *next;
};
struct LIST {
struct NODE *first;
struct NODE *last;
int size;
};
int main(){
struct NODE E;
struct NODE F;
struct LIST L;
E.data = 1;
E.next = NULL;
F.data = 2;
F.next = NULL;
E.next = &F; // not E.next = F;
L.first = &E; // not L.first = E;
L.last = &F; // not L.last = F;
struct NODE *ptr;
ptr = &E; // not ptr = E;
while(ptr != NULL){
printf("%i\n", ptr->data);
ptr = ptr->next;
}
return 0;
}
Recommended to use int main() instead of void main().
Output :-
1
2
I've found the solution or at least some additional information that led me towards the solution minutes after sending the question to SO.
In Wikipedia (https://en.wikipedia.org/wiki/Struct_(C_programming_language)#Pointers_to_struct) I've found the next snippet of code:
struct point {
int x;
int y;
};
struct point my_point = { 3, 7 };
struct point *p = &my_point; /* To declare and define p as a pointer of type struct point,
and initialize it with the address of my_point. */
My mistake was using the pointer to point to the structure and not to the structure's address. Pointers can point only to addresses (they store its value), they cannot point to objects.
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;
}
I'm reading an algorithms book and I found myself stuck on this bit. I create a doubly linked list and when I try to print out its contents it prints out what I believe is address or some other value that is not relevant to what I want. Here is the code:
typedef struct double_element *dElement;
struct double_element
{
int value;
dElement prev;
dElement next;
};
dElement createNewDListWithElements(int count)
{
dElement element = malloc(sizeof(dElement));
element->value = 1;
element->next = NULL;
element->prev = NULL;
dElement previous = element;
for (int i = 1; i < count; i++) {
dElement el = malloc(sizeof(dElement));
el->value = i;
el->next = NULL;
el->prev = previous;
previous->next = el;
previous = el;
}
return element;
}
void printDList(dElement node)
{
printf("printing doubly linked list:\n");
while (node) {
printf("%i\n", node->value);
node = node->next;
}
printf("end printing double linked list\n");
}
Here is the output:
printing doubly linked list:
1
1070320
1070336
1070352
1070368
1070384
1070400
1070416
1070432
1070448
end printing double linked list
Your problem is that you are trying to allocate space for a struct double_element, but you only ask for enough space to store a struct double_element*.
The problem is that you are allocating space for a pointer instead of the struct itself, the reason the dangerous typedef of the pointer, if you want to guarantee the allocation is correct regardless of the typedef's in your code you can do this
dElement element = malloc(sizeof(*element));
that would allocate space for the struct, just as if you had called
dElement element = malloc(sizeof(struct double_element));
you can see that the typedef is harmful, a pointer should be explicitly a pointer, so the correct way to write the code without falling in this kind of issue is
struct double_element *element = malloc(sizeof(struct double_element));
/* ^ don't skip this no matter what */
also, you should make clear what the struct names are and how you name your variables, you could for example use CamelCase for the struct names, and lower case with underscores for your variables, something like this
struct DoubleElement *element = ...
it would make it clear that DoubleElement is the name of a struct, and even though you can leave the struct instead of tyepdefing it, because that makes it even clearer.