How to initialize a pointer outside of main? - c

I am trying to implement nodelist in c:
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int value;
void *next;
} node_t;
void printlist(node_t*head){
for(node_t*i=head;i;i=i->next)
printf("%i\n",i->value);
}
node_t create(int value){
node_t *ret = malloc(sizeof(node_t));
ret->value=value;
ret->next=0;
return *ret;
}
int main(){
int i=0;
node_t*head=0;
for(node_t*tmp;i++<10;head=tmp)
{
*tmp=create(i+100);
tmp->next=head;
}
printlist(head);
}
and in the for loop, I am using node_t* pointer which is assign to already initialized (via malloc) struct outside in create function. But the program emits:
warning: ‘tmp’ may be used uninitialized in this function [-Wmaybe-uninitialized]
*tmp=create(i+100);
Command terminated
So how to assign a dereferenced pointer to already initialized data in c?

When you first enter the loop, tmp doesn't point to anything. Because of that, it's invalid to dereference the pointer.
Also, you have a memory leak in create. You dynamically allocate memory for a node but then return a copy of that node, leaving nothing to point to the allocated memory.
You can fix these issues by returning a pointer from the function:
node_t *create(int value){
node_t *ret = malloc(sizeof(node_t));
ret->value=value;
ret->next=0;
return ret;
}
And subsequently saving that pointer in tmp in the calling function:
tmp=create(i+100);

For starters the function create should return pointer to the created dynamically node. Otherwise you will be unable to free allocated nodes because the function returns a copy of a created node.
So rewrite the function at least like
node_t * create(int value){
node_t *ret = malloc(sizeof(node_t));
ret->value=value;
ret->next=0;
return ret;
}
In the for loop in main you are using an uninitialized pointer tmp. So with the function implementation of create as you defined it the loop invokes undefined behavior due to the underlined assignment
for(node_t*tmp;i++<10;head=tmp)
{
*tmp=create(i+100);
^^^^^^^^^^^^^^^^^^
tmp->next=head;
}
So after changing the function create change the loop like
for(node_t*tmp;i++<10;head=tmp)
{
tmp=create(i+100);
tmp->next=head;
}
Here is your updated program.
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int value;
void *next;
} node_t;
void printlist(node_t*head){
for(node_t*i=head;i;i=i->next)
printf("%i\n",i->value);
}
node_t * create(int value){
node_t *ret = malloc(sizeof(node_t));
ret->value=value;
ret->next=0;
return ret;
}
int main(){
int i=0;
node_t*head=0;
for(node_t*tmp;i++<10;head=tmp)
{
tmp=create(i+100);
tmp->next=head;
}
printlist(head);
}
Its output is
110
109
108
107
106
105
104
103
102
101

Related

Why do I get a segmentation fault when trying to create a linked list using structures?

I am writing a code to create a linked list using structures in C language.
I have defined the structure with a data type and a pointer to structure type. Further I have used typedef to typecast this to Node_s.
I am using a function to initialise the first node; which basically won't contain any value but just returns the headpointer, which I will use to point to my next structure (node).
In the main block, I am initialising a structure pointer with Null value and then feeding the value from initialiser function to this pointer.
But this code is returning zsh: segmentation fault . Can someone explain me the issue!
#include <stdio.h>
#include <stdlib.h>
//Node* Initialize;
typedef struct Node {
int data;
struct Node* next;
} Node_s;
Node_s* Initialize(){
Node_s init_node;
Node_s* headlist;
init_node.data = 0;
init_node.next = headlist;
return headlist;
}
int main()
{
Node_s* ptr = NULL;
ptr = Initialize();
// 1st Node
ptr->data = 1;
Node_s* ptr2 = NULL;
ptr->next = ptr2;
// 2nd Node
ptr2->data = 1;
ptr2->next = NULL;
printf(" \n done deal %d", (*ptr2).data );
return 0;
}
main(): the variable ptr is uninitialized as returned from Initialize(). If it points to NULL or any other memory you don't have access to it will segfault when you deference it's members (ptr->data).
main(): the variable ptr2 is initialized to NULL, then you try to dereference it set its members. This will trigger a segfault if you get there.
Initialize(): init_node is a local variable and has no effect outside the function.
Initialize(): headlist is uninitialized as I mentioned above.
Initialize(): I suggest you change the signature to Node_s *Initialize(int data) so you can set the data to the value you need instead of a dummy value.
Here's a better starting point:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* next;
} Node_s;
Node_s *Initialize(int data) {
Node_s *headlist = malloc(sizeof(*headlist));
if(!headlist) {
printf("malloc failed\n");
return NULL;
}
headlist->data = data;
headlist->next = NULL;
printf("done deal %d\n", headlist->data);
return headlist;
}
int main() {
Node_s *ptr = Initialize(1);
if(!ptr)
return 1;
ptr->next = Initialize(2);
if(!ptr->next)
return 1
return 0;
}
The next step would be to eliminate the printf("done deal ...) statement in favor of a function that prints your linked list. Then write a function that frees the linked list. Then write a function that can Append(int data) an element to your list to replace Initialize().

C program acting weird

I've started implementing a circular queue in C, and I have the following lines of code:
#include <stdio.h>
#include <stdlib.h>
#include "cirq.h"
//allocate a circular queue
cirq cq_alloc(void){
cirq cq = NULL;
element *head;
element *tail;
if((head = malloc(sizeof(struct element*))) &&
(tail = malloc(sizeof(struct element *)))){
head->content = 0; // head node keeps track of size.
tail->content = NULL;
head->next = tail;
tail->next = head;
cq = &head;
} else {
printf("ERROR: No space for more cqueues.\n");
}
return cq;
}
int cq_size(cirq q){
return (int)(*q)->content;
}
int main(){
cirq q = cq_alloc();
printf("Size of element ptr %lu\n", sizeof(struct element *));
printf("%d\n", cq_size(q));
return 0;
}
Now when I compile and run this program, having commented out the line in main that prints out sizeof(struct element *)), the program runs fine and I get the right size of the queue, 0. When I leave the line in, the size of the struct is printed out, but after that I get a segmentation fault: 11. Also, to make things clear, the struct element has void *data and struct element *next fields. How can adding in a line that prints stuff change the behavior of the program so much?
EDIT: cirq.h
#ifndef CIRQ_H
#define CIRQ_H
typedef struct element **cirq; // cirq handle
typedef struct element {
void *content;
struct element *next;
} element;
extern cirq cq_alloc(void);// allocate a queue
extern int cq_size(cirq q);// return the size of a queue
extern void cq_enq(cirq q, void *value);// add a value to the queue
extern void *cq_deq(cirq q);// dequeue and return a queue value
extern void *cq_peek(cirq q);// return the value at the queue head
extern void cq_rot(cirq q);// requeue the head element at the tail
extern void cq_free(cirq q);// return all space allocated to queue
#endif
This is a bad smell:
if((head = malloc(sizeof(struct element*))) &&
You're mallocing the size of a pointer. I think you meant to malloc the struct itself...?
It doesn't really matter what cirq is, the fact that you return the address of a local object is the problem.
This here
cq = &head;
is causing the undefined behavior, because that's the address of the pointer head which is stored locally in the function only, when the function returns it's deallocated and thus invalid. Using it elsewhere (outside the function) is Undefined Behavior.
Also, do not typedef a pointer. Never do that, let the code reader know that it is a pointer.

Creating a binary tree but it doesn't work — tree is always null

I am creating a code to insert the elements in tree, but tinsert function does not insert; what is wrong with my code? I have checked many times but tree is always NULL.
The code has only 2 functions: one to insert, and second to show it in preorder.
#include<stdio.h>
#include<stdlib.h>
struct btree {
int val;
struct btree *left;
struct btree *right;
};
static int c=0;
typedef struct btree node;
void tinsert( node *n,int a)
{
c++;
printf("%d\n",c);
if(n==NULL)
{
n=(node *)malloc(sizeof(node));
n->left=NULL;
n->right=NULL;
n->val=a;
//printf("adding root %d\n",n->val);
//n=temp;
}
else if(a>=(n->val))
tinsert(n->right,a);
else
tinsert(n->left,a);
return ;
}
void preorder_display(node *n)
{
if(n!=NULL)
{
printf("%d\n",n->val);
preorder_display(n->left);
preorder_display(n->right);
}
else
printf("tree is null\n");
}
int main()
{
//int N;
//int num[100];
//int i;
node *ntree=NULL;
tinsert(ntree,4);
tinsert(ntree,6);
tinsert(ntree,8);
tinsert(ntree,1);
printf("tree is \n");
preorder_display(ntree);
return 0;
}
tinsert works on a local copy of your ntree, it doesn't change the one in your main. You can fix it by passing a pointer to it (i.e.: double pointer, pointer to a pointer).
So your tinsert will look like this:
void tinsert( node **n,int a)
And in your main you'll call it like this:
tinsert(&ntree,4);
Of course, you'll need to adjust the code in tinsert to de-reference the pointer and access it correctly.
Or allocate the root node in your main.
you pass your root node ntree to tinsert function by value, so when when the function is done you will stay with original value of ntree which is NULL.
You better rewrite your function, so you will pass pointer to pointer
void tinsert( node **n,int a)
//and invocation is like that :
tinsert(&ntree,4);
when you pass ntree from main to tinsert function,
new copy is created to your node*n;
One way is to make use of pointer to pointer
Or second solution is here:
Here is a solution:
#include<stdio.h>
#include<stdlib.h>
struct btree{
int val;
struct btree *left;
struct btree *right;
};
static int c=0;
typedef struct btree node;
node* tinsert( node *n,int a)
{
c++;
printf("%d\n",c);
if(n==NULL)
{
n=(node *)malloc(sizeof(node));
n->left=NULL;
n->right=NULL;
n->val=a;
//printf("adding root %d\n",n->val);
//n=temp;
}
else if(a>=(n->val))
tinsert(n->right,a);
else
tinsert(n->left,a);
return n;
}
void preorder_display(node *n)
{
if(n!=NULL)
{
printf("%d\n",n->val);
preorder_display(n->left);
preorder_display(n->right);
}
else
printf("tree is null\n");
}
int main()
{
//int N;
//int num[100];
//int i;
node *ntree=NULL;
ntree=tinsert(ntree,4);
ntree=tinsert(ntree,6);
ntree=tinsert(ntree,8);
ntree=tinsert(ntree,1);
printf("tree is \n");
preorder_display(ntree);
return 0;
}
C supports the pass by value only. However, this does not prevent you from modifying the value of a variable from another function, because you can always refer to a variable using it's memory; and in C it's done through pointers, an abstraction representing a memory location.
When you pass a value to the function, the value of the actual parameter is copied to the value of formal parameter. Note that a pointer's value is the address it points to. So, this value is copied into the formal parameter. So the new pointer inside the function points to the exact same location your original variable. You can deference the pointer anytime to manipulate it's value.
Here, you are required to manipulate a pointer. So you pass a pointer-to-pointer to the function:
tinsert(&ntree,4);
In your function, you deference it to get your original pointer; like the following:
void tinsert(node **n, int a)
{
//...
*n = malloc(sizeof(node));
//...
}

Stack TOP pointer is always null

I am creating a new stack using linked list. I dont know why the TOP pointer is always pointing to NULL. I think I am not setting the top pointer correctly, or it is not visible outside the function.
#include "stdio.h"
#include "stdlib.h"
typedef struct StackItem
{
int itemValue;
struct StackItem* NextItemPtr;
}StackItem;
typedef struct Stack
{
struct StackItem *TOP;
}Stack;
int IsStackEmpty(StackItem *TOP)
{
if(TOP==NULL)
return 1;
}
void pushItem(StackItem *headPtr,int n)
{
StackItem* Newnode;
Newnode=(StackItem*)malloc(sizeof(StackItem));
Newnode->itemValue=n;
printf("Checking Head TOP %d\n\n",IsStackEmpty(headPtr)); //Everytime it is giving 1
Newnode->NextItemPtr=IsStackEmpty(headPtr)?NULL:headPtr;
headPtr=Newnode;
}
int main()
{
Stack* stackptr;
stackptr=(Stack*)malloc(sizeof(Stack));
stackptr->TOP=NULL;
pushItem(stackptr->TOP,3);
pushItem(stackptr->TOP,6);
return 0;
}
This statement does nothing for the caller:
headPtr=Newnode;
You can:
Pass a double pointer and assign to *headPtr
Return Newnode instead of assigning to headPtr
This C FAQ explains this very subject.
headPtr = Newnode;
Since headPtr is an argument of the function, it's passed by value. Modifying it inside the function does not have any effect in the caller. You need to pass a pointer to it and modify it through the pointer:
void pushItem(StackItem **headPtr, int n)
*headPtr = NewNode;

How to allocate memory?

I am trying to create a linked list in my program and I am not able to allocate memory to the structure pointer using malloc(). How do I allocate memory to variables in GCC? The sample program is given below. How to make it work in gcc?
#include<stdio.h>
#include <alloc.h>
struct node
{
int data;
struct node * link;
};
void insert (struct node *p, int d)
{
struct node *temp;
temp = malloc(sizeof(struct node));
temp->data=d;
temp->link=NULL;
if(p==NULL)
{
p=temp;
}
else{
while(p->link!=NULL)
p=p->link;
p->link=temp;
}
}
void disp(struct node *p)
{
while(p!=NULL)
{
printf("%d\n",p->data);
p=p->link;
}
}
int main()
{
struct node *p;
p=NULL;
insert(p,7);
insert(p,9);
disp(p);
}
The error I'm encountering is:
Line 18: error: alloc.h: No such file or directory
In function 'insert':
Line 13: warning: incompatible implicit declaration of built-in function 'malloc'
malloc is in <stdlib.h>. Include that.
Reading the man page for that function would have given you that information. It's not compiler-dependent.
malloc is declared in <stdlib.h>, so that's what you want to #include.
The definition of malloc is in the stdlib.h file:
#include <stdlib.h>
instead of alloc.h.
Like the others say: your error occurs because you have to include stdlib.h instead of alloc.h
To get your list printed, you have to modify p in insert. Currently, you're passing NULL every time you call insert. Change your code that way (pass a pointer-to-pointer to insert):
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node * link;
};
/* note **p instead of *p */
void insert (struct node **p, int d)
{
struct node *temp;
temp = malloc(sizeof(struct node));
temp->data=d;
temp->link=NULL;
if(*p==NULL)
{
*p=temp;
}
else{
while((*p)->link!=NULL)
*p=(*p)->link;
(*p)->link=temp;
}
}
void disp(struct node *p)
{
while(p!=NULL)
{
printf("%d\n",p->data);
p=p->link;
}
}
int main()
{
struct node *p;
p=NULL;
insert(&p,7);
insert(&p,9);
disp(p);
}
and it will print
7
9

Resources