Excuse the beginner level of this question. I have the following simple code, but it does not seem to run. It gets a segmentation fault. If I replace the pointer with a simple call to the actual variable, it runs fine... I'm not sure why.
struct node
{
int x;
struct node *left;
struct node *right;
};
int main()
{
struct node *root;
root->x = 42;
printf("Hello world. %d", root->x);
getchar();
return 0;
}
What is wrong with this code?
struct node *root;
root->x = 42;
You're dereferencing an uninitialized pointer. To allocate storage for the node:
struct node *root = malloc(sizeof(struct node));
You could also allocate a node on the stack:
struct node root;
root.x = 42;
In order to use a pointer to access something, the pointer must be pointing at that something. In order for the pointer to be pointing at that something, that something must exist. Creating a pointer does not create anything for it to point at. You must do so explicitly, either by dynamic allocation (malloc()), stack allocation (i.e. a local variable) or by pointing to something that already exists (e.g. a static instance, such as a global; a value that was passed in as a parameter; etc.).
After struct node *root; line add the
root = (sturct node*) malloc(sizeof(struct node));
Also, before Return 0 line add the
free(root);
Related
I've created a Stack structure in C. When the stack is initialized with a value, I am able to print it back and receive the correct output. However, after pushing a new string, the print function prints what appears to be a random character (ASCII 177).
Originally, I implemented this project with pointers, but I was unable to get it working. Instead, I opted to only use a pointer for the Node *nodes member of Stack. That way, when I need to grow the stack, I can just multiply the amount of memory required by Stack.size. However, this approach has not worked yet either.
#define MAX_DATA 64
struct Node{
char val[MAX_DATA];
};
struct Stack{
int size;
struct Node *nodes;
};
These are used as follows:
struct Node node = {.val = "Test"};
struct Stack stack = newStack(node);
printStack(stack);
The newStack function initializes nodes properly. For the sake of inclusion:
struct Stack newStack(struct Node node)
{
struct Stack stack;
stack.size = 1;
stack.nodes = (struct Node*) malloc(sizeof(struct Node));
stack.nodes[0] = node;
return stack;
}
The stack is then printed iteratively in printStack(), with stack.size being the upper bound of the for-loop.
The trouble comes when I try to run:
struct Node node2 = {.val = "Test1"};
push(stack, node2);
printStack(stack);
The push function aims to create a temporary stack and assign the value of the stack to it. After this, the size is incremented, the pointer to the nodes is freed, and new memory is allocated, with room for a new member at the end.
void push(struct Stack stack, struct Node node)
{
struct Stack temp_stack = stack;
stack.size += 1;
free(stack.nodes);
stack.nodes = (struct Node*) malloc(sizeof(struct Node) * stack.size);
for(int i = 0; i < temp_stack.size; i++){
stack.nodes[i] = temp_stack.nodes[i];
}
stack.nodes[stack.size - 1] = node;
}
Needless to say, this doesn't execute properly.
The expected output would be:
Test
Test1
But, instead, I receive only ASCII-177. It is also worth noting that the execution hangs after it prints that and moves to the new line. This results in Aborted (core dumped).
Am I improperly freeing and re-allocating memory? Any help would be appreciated. Thank you in advance!
It's worth remembering that in C, passing a struct to a function is pass-by-value, i.e., the function gets a copy of the struct. All members of the struct, including pointer variables (but not whatever the pointer references), are duplicated.
So in the push function, think about what happens to the original when you modify this copy (e.g., stack.size += 1, and also when you free() the stack.nodes.
Thank you to peekay for the recommendations. I ended up doing a re-write. It became quite a bit simpler. I did remove a layer of "visibility" by storing the nodes as a pointer, but I suppose this implementation is a bit more true to the data structure.
Node is implemented as a means to hold data, and the user doesn't interact with it directly. It also points to the following Node. Stack is implemented to hold the top Node, and also the size of the Stack.
Node:
struct Node{
char val[MAX_DATA];
struct Node *next;
};
Stack:
struct Stack{
struct Node *top;
int size;
};
Push:
void push(struct Stack *stack, char *newVal)
{
struct Node *newNode;
newNode = (struct Node*) malloc(sizeof(struct Node));
strcpy(newNode->val, newVal);
newNode->next = stack->top;
stack->top = newNode;
stack->size++;
}
Usage:
struct Stack stack;
newStack(&stack);
push(&stack, "Test");
push(&stack, "Test1");
push(&stack, "Test2");
push(&stack, "Test3");
Complete Code
Updated, accessible Nodes
So, I wanted to create a stack as follows:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node{
int data;
struct node *link;
}node;
typedef struct Stack{
struct Node *topnode;
int count;
}stack;
void push(int data, stack *ourstack){
node newnode;
newnode.data = data;
ourstack.topnode = &newnode;
}
int main()
{
stack mystack;
push(1,mystack);
printf("%d",(mystack.(*topnode).data));
}
but I do get errors. I am a bit confused here. Inside the push() function, in the last line, I tried various ways of implementing it right but I failed each time. Now, my thinking is, ourstack is a pointer pointing to a struct Stack. And the topnode is also a pointer inside a structure of a stack which points to another node structure. So, should not (*ourstack).(*topnode) = newnode or ourstack.topnode = &newnode work? Why?
Neither work because newnode is on the stack and once the code exits push, it will no longer exist. You need to allocate it dynamically.
void push(int data, stack *ourstack){
node *newnode;
newnode = malloc(sizeof(*newnode));
newnode->next = ourstack->topnode; // Point the next of the new node to the top node of the stack
newnode->data = data;
ourstack->topnode = newnode;
}
And also you need to initialise mystack properly in main or else you risk undefined behaviour as topnode could be NULL or it could have a random value.
stack mystack;
mystack.topnode = NULL;
mystack.count = 0;
variable in a method, only exists in stack, will be unavailable after exit method. since you wish keep it after call of push, you need alloc a node with function like malloc, which will save data in heap. and you have to free it after you do not need it any more.
There are number of bugs in your program.
ourstack is pointer variable of structure type, while accessing data using ourstack use -> operator instead of dot operator
Replace
ourstack.topnode = &newnode;
with
ourstack->topnode = &newnode;
there is a conflict in push function definition and function call, you are passing just mystack and catching with struct pointer variable. pass the address of mystack, your function call should be
push(1,&mystack);
newnode is the local variable declared in push function and whatever you are trying with newnode it will reflects in this function only, not outside of this. So Allocate memory dynamically for newnode and do the operation.
void push(int data, stack *ourstack){
node *newnode;
newnode = malloc(sizeof(stack));
newnode->data = data;
ourstack->topnode = newnode;
}
Once compiled successfully debug the code using gdb and analyze.
I've been reviewing the basics of singly linked list In C with materials from Stanford CS Library, where I came cross the following code:
struct node{
int data;
struct node* next;
};
struct node* BuildWithDummyNode(){
struct node dummy;
struct node* tail = & dummy; // this line got me confused
int i;
dummy.next = NULL;
for (i=1;i<6;i++){
Push(&(tail->next), i);
tail = tail->next;
}
return dummy.next;
}
Probably not revenant, but the code for Push() is:
void Push(struct node** headRef, int data){
struct node* NewNode = malloc(sizeof(struct node));
newNode->data = data;
newNode->next = *headRef;
*headRef = newNode;
}
Everything runs smoothly, but I've always been under the impression that whenever you define a pointer, it must point to an already defined variable. But here the variable "dummy" is only declared and not initialized. Shouldn't that generate some kind of warning at least?
I know some variables are initialized to 0 by default, and after printing dummy.data it indeed prints 0. So is this an instance of "doable but bad practice", or am I missing something entirely?
Thank you very much!
Variable dummy has already been declared in the following statement:
struct node dummy;
which means that memory has been allocated to it. In other words, this means that it now has an address associated with it. Hence the pointer tail declared in following line:
struct node* tail = & dummy;
to store its address makes perfect sense.
"But here the variable "dummy" is only declared and not initialized."
The variable declaration introduces it into the scope. You are correct in deducing it's value is unspecified, but to take and use its address is well defined from the moment it comes into scope, right up until it goes out of scope.
To put more simply: your program is correct because you don't depend on the variables uninitialized value, but rather on its well defined address.
I have created a struct with a char variable in it. I want to assign a string value to it when using it inside of a method and then print it. I have been looking around but can't find a valid answer, but can't find what I'm doing wrong. Why am I getting the error below?
Here is what I have tried:
struct node{
char *val;
struct node *first;
struct node *last;
};
void main(){
struct node *new_node;
new_node =(struct node *)malloc(sizeof(struct node));
new_node.val = "a";
printf("%s",new_node.val);
}
I get the error:
request for member 'val' in something not a structure or union
new_node should be accessed as a pointer and not an instance.
try new_node->val instead of new_node.val
response to edited question
As you have changed from char val to char *val you will need additional processing:
allocate memory for *val : new_node->val=(char*)malloc(sizeof(char))
assignment will need to dereference the pointer : *(new_node->val)="a"
Print statement should also dereference the pointer : printf("%c",*(new_node->val))
you should free the val pointer before freeing new_node: free(new_node->val)
new_node.val should be replaced with new_node->val. since new_node is a pointer. Keep in mind that new_node->val (often refereed as the arrow operator) is the shorthand for (*new_node).val.
Also i believe you can write:
node *new_node = malloc(sizeof(node));
For easier reading and cleaner code since malloc will just return a pointer to a given memory address. Use -Wall or other warning flags when you compilate your program to experience less logical errors or seg faults.
I dont understand the cause of the segmentation fault here.
The code is:
struct node {
int data;
struct node* next;
};
void add(int a,struct node *lista)
{
struct node *p;
p=(struct node*)malloc(sizeof(struct node*));
p->data=a;
p->next=NULL;
while(lista->next!=NULL) <--- The segmentation fault is here.
lista=lista->next;
lista->next=p;
return lista;
}
int main(void)
{
struct node *list=NULL;
list_print(list);
list=node123();
list_print(list);
add(7, &list);
list_print(list);
return 0;
}
the add function which adds a new node to the end of the list worked perfectly like this on a friends computer and setup. I get segmentation fault. i think the problem is the lista->next expression but I don't understand why. Any ideas?
void add(int a,struct node *lista)... 2nd parameter is a struct node pointer.
struct node *list=NULL; -- list is a struct node pointer.
add(7, &list); -- &list is a struct node **; this is incorrect and likely to cause add()'s `while(lista->next!=NULL) to fail its dereference.
p = (struct node*)malloc(sizeof(struct node*));
This is certainly wrong. You must not allocate memory sized as the pointer itself, but as big as the actual structure. Use
p = malloc(sizeof(struct node));
or even better
p = malloc(sizeof(*p));
And don't for the love of God cast the return value of malloc().
Also, you declare list as struct node *, and your add() function also expects a struct node * - so it's erronous to pass its address to the function. Instead of
add(7, &list);
write
add(7, list);
You're passing the address of list, but the funciton takes only a pointer, in order to pass 'list' by reference, You've got to chagne the decliration of add to:
void add(int a,struct node **lista);
and then use (*lista) instead of just 'list' . ex: (*lista)->next ...
You declared 'add' to not return any type of data (void). but you're returning 'list'. either make the function work on a pointer to a pointer to 'list' (taking **list as a parameter instead of *list). or make it return a list type: struct list* add(
1 - you have to check if lista is not null before writhin lista->next
2 - There is an error in the malloc :
p=(struct node*)malloc(sizeof(struct node));
the size to allocate is the size of a node, you allocated the size of a pointer struct node*.
3 - add(7 , lista) not add(7 , &lista) because lista is already a pointer.