Assign function to function field in C - c

I'm trying to assign a function to a variable field, but I get Segmentation fault.
Here is the code:
typedef struct node{
int info;
struct node *link;
void* (*make) (int x);
}node;
void* make_node(int x)
{
node* new_node = (node*)malloc(sizeof(node));
new_node->info = x;
new_node->link = NULL;
return new_node;
}
int main(){
struct node *n;
n->make = make_node;
return 0;
}
What could be wrong?

you need to allocate some space to node on heap or just use a normal variable of the structure instead of a pointer.

Your n variable into main() is uninitialised.
The make_node() function will reserve space for a node structure, so why not call it inside main()?
You may try the code below.
typedef struct {
int info;
struct node *link;
void* (*make) (int x);
} node;
void *make_node(int x)
{
node* new_node = malloc(sizeof(node));
new_node->info = x;
new_node->link = NULL;
return new_node;
}
int main() {
struct node *n;
n = make_node(1);
free (n);
return 0;
}
p.s avoid casting malloc returns
p.s.2 pay attention for the same problem when you'll use struct node *link inside node
p.s.3 remember to free() unused malloc()ed variables.

You have forgotten to assign a value to n.
Change the return type of make_node to node*
Do n=make_node(x)
And I strongly advise reading http://www.amazon.com/gp/aw/d/0131103628/ref=redir_mdp_mobile
This would be the best thing you can do now.

With the existing infrastructure, you could write:
typedef struct node
{
int info;
struct node *link;
void *(*make)(int x);
} node;
void *make_node(int x)
{
node* new_node = (node*)malloc(sizeof(node));
new_node->info = x;
new_node->link = NULL;
new_node->make = make_node;
return new_node;
}
int main(void)
{
struct node *n = make_node(1);
...use the newly allocated node...
return 0;
}
This allocates the node before you try to write to it. It also fully initializes the node by setting every field to a known value. If you need a different function pointer for the make member, you can adjust afterwards.

You can allocate space for n on the stack this way:
int main() {
struct node n;
n.make = make_node;
return 0;
}
Otherwise you'd have to allocate it on the heap perhaps as a global variable or using malloc().

Related

creating a list of nodes with C

I want to createe a list of nodes that links to each other, I use head to remember the address of the first node, prev to link, and newdata to get the input, but it turns out that my head prev and newdata are all in the same address, can someone help me with this plz
typedef struct node
{
void* stdPtr;
struct node* link;
}NODE;
NODE* createNode(void* std)
{
NODE* nodePtr;
nodePtr=(NODE*)malloc(sizeof(NODE));
nodePtr->stdPtr=std;
nodePtr->link=NULL;
return nodePtr;
}
typedef NODE* nodePtr;
int main(void)
{
FILE* fin;
fin=fopen("input.txt","r");
//define
int i=0;
intPtr ID,grade;
STD* stdinfo;
nodePtr head=NULL;
nodePtr prev=(nodePtr)malloc(sizeof(NODE));
//nodePtr newdata=(nodePtr)malloc(sizeof(NODE));
prev=head;
//malloc space to ptr
ID=(intPtr)malloc(sizeof(int));
grade=(intPtr)malloc(sizeof(int));
stdinfo=(STD*)malloc(sizeof(STD));
//read student data and compare
while(fscanf(fin,"%d%d",&(stdinfo->ID),&(stdinfo->grade))!=EOF)
{
nodePtr newdata=(nodePtr)malloc(sizeof(NODE));
newdata=createNode(stdinfo);
if (prev==NULL)
{
prev=newdata;
head=prev;//為什麼只有在這裡=prev後面會跑掉?
}
printf("%d %d\n",*(int*)head,*(int*)prev);
if(prev->link!=NULL)
{
prev=prev->link;
}
prev->link=newdata;
}
fclose(fin);
return 0;
}
Important parts are missing (types, input.txt) to run your program which makes it harder to help you.
You create an instance of STD prior to the loop, then overwrite whatever data you store in it on each iteration and store the address of that one instance in each node. You need to create an instance of both NODE and STD per loop iteration (or change the definition of NODE so it can hold the STD data instead of a pointer to STD).
You use this pattern a couple of times which allocate data, then immediately leak the data by overwriting the pointer:
nodePtr prev=(nodePtr)malloc(sizeof(NODE));
prev=head;
...
nodePtr newdata=(nodePtr)malloc(sizeof(NODE));
newdata=createNode(stdinfo);
Here is more straight forward version to get you going:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
void *stdPtr;
struct node* link;
} NODE;
NODE* createNode(void *std, NODE *prev) {
NODE *nodePtr = malloc(sizeof(NODE));
nodePtr->stdPtr=std;
nodePtr->link=prev;
return nodePtr;
}
void printNodes(NODE *tail) {
for(; tail; tail = tail->link) {
printf("%s\n", (const char *) tail->stdPtr);
}
}
int main(void) {
NODE *tail = NULL;
tail = createNode("hello", tail);
tail = createNode("world", tail);
printNodes(tail);
}

Does array initialize memory in c? [duplicate]

This question already has answers here:
initial value of int array in C
(10 answers)
Closed 2 years ago.
Having this linked list:
#include <stdio.h>
#include <stdlib.h>
struct node {
int value;
struct node *next;
};
typedef struct node node_t;
void printlist(const node_t*);
node_t *create_node(int);
int main(void){
int values[3] = {1,2,3};
node_t *nodes[3];
for(int i =0; i<3 ; i++)
{
nodes[i] = create_node(values[i]);
if(i!=2)
nodes[i]->next = nodes[i+1]; //HERE, can I assign next (un)initialized node?
}
node_t *header = nodes[0];
printlist(header);
}
void printlist(const node_t* header){
for(const node_t *i = header; i; i=i->next)
printf("value is %i\n",i->value);
}
node_t *create_node(int value){
node_t *new = malloc(sizeof(node_t));
new->value=value;
new->next = 0;
return new;
}
Which gives:
value is 1
value is 29590344
Command terminated
As I can see from output, the first node (header), does not have assign next struct member, which should happened from the loop. But I am assigning the next (pointer to new node) to an (un)initialized member from array (of pointer to nodes). I expect a initilization of array should also initilize a memory, when it has size. But does it? If so, then I do not understand why the assignment does not work, otherwise I understand and have to implement other loop. Thanks for answers.
Your code does not create the dynamic list as you have an array of 3 nodes. next is not needed.
You probably want something like this.
/* you need to check if memory allocation was successful */
#include <stdlib.h>
#include <stdio.h>
typedef struct node {
int value;
struct node *next;
} node_t;
void printlist(const node_t*);
node_t *append_node(node_t *, int);
int main()
{
node_t *head = NULL, *parent = head;
for(int x = 0; x < 10; x++)
if(!head)
{
head = append_node(NULL, x);
parent = head;
}
else
{
parent = append_node(parent, x);
}
printlist(head);
}
void printlist(const node_t* head){
while(head)
{
printf("value is %i\n",head->value);
head = head -> next;
}
}
node_t *append_node(node_t *parent, int value){
node_t *new = malloc(sizeof(*new));
new->value=value;
new->next = NULL;
if(parent) parent -> next = new;
return new;
}

Double pointer in linked list

I almost figured out this code, but there are two details I can't figure out.
I found this code on YouTube.
source: https://www.youtube.com/watch?v=VOpjAHCee7c
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int vaule;
struct node *next;
}node_t;
void printlist(node_t *head)
{
node_t *temp = head;
while(temp != NULL)
{
printf("%d - ", temp->vaule);
temp = temp->next;
}
printf("\n");
}
node_t *create_node(int var)
{
node_t *res = malloc(sizeof(node_t));
res->vaule = var;
res->next = NULL;
return res;
}
node_t *insert_at_head(node_t **head, node_t *node_to_insert)
{
node_to_insert->next = *head;
*head = node_to_insert;
return node_to_insert;
}
void find_node()
int main()
{
node_t *tmp;
node_t *head = NULL;
for(int i = 0; i < 15; i++)
{
tmp = create_node(i);
head = insert_at_head(&head, tmp);
}
printlist(head);
return 0;
}
1) Why do we use the nested struct?
typedef struct node{
int vaule;
struct node *next;
}node_t;
I know about nested structures but I didn't understand why we use it here.
2) Why do we use double pointer?
node_t *insert_at_head(node_t **head, node_t *node_to_insert)
{
node_to_insert->next = *head;
*head = node_to_insert;
return node_to_insert;
}
if I change this code like this:
node_t *insert_at_head(node_t *head, node_t *node_to_insert)
{
node_to_insert->next = head;
return node_to_insert;
}
then nothing will change
Why do we use the nested struct?It's not a nested struct. struct node *next is a pointer, and as its name indidcates, it points to the next element.
Why do we use double pointer? Read this: How do I modify a pointer that has been passed into a function in C?
1)Why do we use the nested struct?
It is not a nested struct, but a linked list. Each node has a pointer to the next node (or to NULL for the last node of a list
2)Why do we use double pointer?
C only passes parameters by value. The idiomatic ways to change a variable from the caller are:
assign the return value to that variable. It is the best way, but you can only return one single value that way
pass a pointer to the variable and use the pointer to change the value. As we want to change the value of head which is already a pointer, we have to pass a pointer to pointer.
Here the write of the code has decided to change the passed header to clearly show that it is an input/output parameter, and also returns it because it had no better value to return.

What is wrong in the stack implementation using linked lists?

I am trying to implement a stack using linked list. Here is my code:
#include<stdio.h>
//implementation of stack
struct Node{
int data;
struct Node* next;
struct Node* prev;
};
struct Stack{
struct Node* headNode;
struct Node* presentNode;
int size;
};
struct Node* newNode()
{
struct Node* node;
return node;
}
struct Stack* newStack()
{
struct Stack* stack;
stack->headNode = newNode();
stack->presentNode = stack->headNode;
stack->size=0;
return stack;
}
int isempty(struct Stack* s)
{
if(s->headNode->next != NULL)
return 0;
return 1;
}
void push(struct Stack* s,int data)
{
struct Node* node = newNode();
node->data = data;
node->next = NULL;
s->presentNode->next = node;
node->prev = s->presentNode;
s->presentNode = node;
s->size ++;
}
int pop(struct Stack*s)
{
if(isempty(s)==1)
return 0;
int data = s->presentNode->data;
s->presentNode->prev->next = NULL;
s->presentNode = s->presentNode->prev;
s->size --;
return data;
}
int main()
{
struct Stack* stack = newStack();
int data = 0,type;
printf("Enter '1' if new element to be added or '0' if the latest element is to be deleted.\n");
while(data!=-1)//unbounded stack
//takes input until data==-1
{
scanf("%d",&type);
if(type)
{
printf("Enter the element:\t");
scanf("%d",&data);
if(data==-1)
continue;
push(stack,data);
}
else
printf("%d is popped out of the list!\n",pop(stack));
}
return 0;
}
But I am getting run-time error. Since I am new to pointers (I am a Java guy), I am pretty confused where my error is, although I am sure it is due to pointers.
You do not allocate memory for your new nodes:
struct Node* newNode()
{
struct Node* node;
return node;
}
Local variable node is an uninitialized pointer. As soon as you use the return value of this function, you have Undefined Behaviour.
Edit:
The same problem is true for newStack:
struct Stack* newStack()
{
struct Stack* stack;
stack->headNode = newNode();
...
return stack;
}
As soon as you dereference stack, you have Undefined Behaviour.
You have multiple problems. For starters
In your newStack() function, you do not have a return statement, so using the return value causes undefined behavior.
You need to allocate memory to pointers (i.e., make pointers to point to valid memory) before you can actually dereference them. In your case
struct Stack* stack;
stack->headNode
is an attempt to use uninitialized memory which again causes UB.

Segment Fault when initialization multiple nodes

I am working on a binary search tree in C. I am having a problem with initializing multiple nodes.
typedef struct Node Node;
struct Node{
int* data;
Node* leftChild;
Node* rightChild;
Node* parent;
};
void initNode(Node* node, int* data){
node->data = data;
node->leftChild = NULL;
node->rightChild = NULL;
node->parent = NULL;
}
The above code seems to work fine when calling initNode() only once. But if I attempt to make the second call I get a segment fault.
My main looks like this:
int main(){
Node* node;
Node* node2;
int a = 12;
int b = 15;
initNode(node, &a);
printf("%i \n", *node->data);
}
This works. However if I do this:
int main(){
Node* node;
Node* node2;
int a = 12;
int b = 15;
initNode(node, &a);
initNode(node2, &b);
printf("%i \n", *node->data);
}
I get a segment fault. Any ideas why this behavior is happening?
You have not allocated memory for both node or node2. Since both the pointers are allocated on stack they will have junk values. Its just accident that the first program passes at all.
This function:
void initNode(Node* node, int* data){
node->data = data;
node->leftChild = NULL;
node->rightChild = NULL;
node->parent = NULL;
}
expects node to have already been initialized.
You don't do that in either of your programs. Dereferencing a pointer that hasn't been assigned is undefined behavior. It's just by chance that it worked in your first program. Who knows what memory you're overwriting.
You need to initialize node and node2.
Node* node = malloc(sizeof*node);
Node* node2 = malloc(sizeof*node2);
Just remember to free them once you're finished with them.
A much cleaner solution is to allocate the Nodes on the stack, so you don't have to worry about calling free.
int main(void) { /* use a valid signature for main() */
Node node; /* just a straight up Node (not a pointer) */
Node node2;
int a = 12;
int b = 15;
initNode(&node, &a); /* use address of operator on nodes */
initNode(&node2, &b);
printf("%i \n", *node->data);
}

Resources