I have the following Structures created:
typedef struct {
char name[15];
int ID;
} Employee;
typedef Employee Item;
typedef struct {
Item items[5];
int size;
} List;
I am using this function call as a peek to see what is being stored in the list:
void Peek (int position, List *L, Item *X);
The function should take the item in the list [L] at [position] and copy its address to [X]. I have for the peek function this:
void Peek (int position, List *L, Item *X) {
Item *B;
B = malloc(sizeof(L->items[position]));
X = B;
}
This assigns X to the same location as B however I think this would result in a memory leak and more importantly if I try to call the ID of item X back in my main, from this function:
int EmployeeID (Employee X) {
return(X.ID);
}
I am returned with 32665 or something along those lines. What would be another way to get the data from L to X?
X and B are both pointers
X = B is pointer assignment, not structure assignment
X is a pass by value parameter, assigning a value to X inside a function has zero impact on the value of X outside the function.
Try this (not a solution, but a step in the right direction):
void Peek (int position, List *L, Item **X)
{
Item *B;
B = malloc(sizeof(L->items[position]));
*X = B;
}
However, the value of L->items[position] is still not assigned to the X space.
Option 2:
void Peek(int position, List *L, Item *X)
{
*X = L->items[position];
}
This assumes that X already points to a malloc'd block of memory. If not, option 3
Option 3:
void Peek (int position, List *L, Item **X)
{
Item *B;
B = malloc(sizeof(L->items[position]));
*X = B;
*B = L->items[position];
}
"The function should ... copy its address to X" ~> The problem with this code:
void Peek (int position, List *L, Item *X) {
Item *B = malloc(sizeof(L->items[position]));
X = B;
}
is that it doesn't change the original pointer passed as a third argument. What you actually need to do is to modify the pointer itself, thus you need to either return this pointer from the function or pass it as Item**, i.e. pointer to pointer:
void Peek (int position, List *L, Item **X) {
Item *B = malloc(sizeof(L->items[position]));
*X = B;
}
...
// and somewhere:
Peek(position, L, &X); // <-- you should pass an address of pointer
Related
Generally, I know that a pointer stores the memory address of another value located in computer memory, for example:
int firstvalue= 5
int * p1;
p1 = &firstvalue; // p1 = address of firstvalue
What happens if we define an operation like the following in a linked list? Does *current=*list means that the value pointed to by current equals to the value pointed to by list? And what does it mean if we define ecur=current?
int function(struct list_t **list){
struct list_t *ecur=NULL;
struct list_t *current=*list;
ecur=current;
}
Update:
What does it do *list=remove(*list, param1, param2)? And why is that?
remove is a function that returns a modified list of list.
Update 2:
Why do we need to define a pointer to pointer in order to modify the list? Is *list a pointer to pointer?
The variable list is a pointer to a pointer to a struct list_t. If we (just as an example) assume that the struct is placed at address 2000 and that the unnamed pointer is at address 1000 it will look like this:
Then you have the initialization that adds two new variables. Both as pointer to a struct list_t.
struct list_t *ecur=NULL;
struct list_t *current=*list;
So the picture now becomes:
Notice that current got the same value as the "some-pointer" in the middle because it is *list that was assigned to current.
Then you have the assignment:
ecur=current;
which means that ecur gets the same value as current and gives the picture:
Update: What does it do *list=remove(*list, param1, param2) ?
It changes the value of the "some-pointer" in the middle of the picture. This is for instance needed if the remove function removes the first element in a linked list.
Why do we need to define a pointer to pointer in order to modify the list? Is *list a pointer to pointer?
Remember that C passes all function arguments by value - the formal argument in the function definition is a different object in memory from the actual argument in the function call. For example:
void swap( int a, int b )
{
int tmp = a;
a = b;
b = tmp;
}
void foo( void )
{
int x = 1;
int y = 2;
swap( x, y );
}
a is a different object in memory than x, and b is a different object in memory than y, so swapping a and b has no effect on x and y. In order to swap the values of x and y, you must pass pointers to them:
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void foo( void )
{
int x = 1;
int y = 2;
swap( &x, &y );
}
The expression *a is the same as x, so writing to *a is the same as writing to x. Same for *b and y.
So, in order for a function to write to a parameter, you must pass a pointer to that parameter:
void foo ( T *arg )
{
*arg = new_value(); // writes a new value to the thing arg points to
}
void bar( void )
{
T var;
foo( &var ); // write a new value to var
}
This is true for any non-array type T. Let's replace T with a pointer type P *:
void foo( P **arg )
{
*arg = new_value(); // write a new *pointer* value to the thing arg points to
}
void bar( void )
{
P *var;
foo( &var ); // write a new pointer value to var
}
The semantics are exactly the same - all that's changed is the type.
If a function has the potential to modify a list * object (say pointing it at a new list head), then you must pass a pointer to that list * object:
void add_node( struct list_t **list, struct list_t *node )
{
if ( !*list || (node->value < (*list)->value) ) // make node new head of list
*list = node;
else
// add node somewhere else in the list
}
int main( void )
{
struct list_t *list = NULL;
...
struct list_t *node = newNode( value );
add_node( &list, node );
...
}
TYPE *p = ptype /*variable of type: TYPE * */;
is not an assignment. It's an initialization, which for an auto-matic (=on-the-stack) p can be rewritten as:
TYPE *p;
p = ptype;
(not TYPE *p; *p=ptype; /*would be a type error*/)
In terms of your example:
struct list_t *current=*list;
sets where current will point to (the same place as what *list points to (*list is also a pointer because list is a doubly-indirect pointer)) without doing anything whatsoever with what current will point at (*current) after the initialization.
All of this is just conceptual, though. Your function doesn't have any externally visible effects so an optimizing compiler should completely delete its body.
I had a similar knot in my head with this post. I'd like to rearrange your function a bit, so it's easier to understand what's going on:
int function(struct list_t **list)
{
struct list_t *current = *list;
struct list_t *ecur = current;
}
If we call this function with an element foo we essentially get this:
struct list_t foo = { .data = "foo" };
struct list_t *bar = &foo;
struct list_t **list = &bar;
struct list_t *current = *list;
struct list_t *ecur = current;
We have five declarations and five assignments. For better readability, I'll write everything down without declarations:
foo = { .data = "foo" };
bar = &foo;
list = &bar;
current = *list;
ecur = current;
Now, let's walk through it:
foo is a struct. It contains the above data-field.
bar is a pointer to struct. It contains the address of foo
list is a pointer to a pointer to struct. It contains the address of bar
current is a pointer to struct. It contains the contents of the contents of list, which is the address of foo
ecur is a pointer to struct. It's identical to current and contains the address bar
In the end we can simplify the whole example to this:
struct list_t foo = { .data = "foo" };
struct list_t *ecur = &foo;
What does it all mean?
list: Because list is a pointer to a pointer you are able to modify bar to point to something completely different, by de-referencing it (*list = ...)
current/ecur: that's what bar originally pointed too. By de-referencing you could change the data-field itself ((*ecur).data = "banana" or better ecur->data)
I hope I could clarify things and didn't make it worse ;)
Why do we need to define a pointer to pointer in order to modify the
list?
Let me add a complete program, albeit short, to illustrate it better. It defines a simply linked list and builds it while keeping it ordered. Yes, I know it would be easier to simply call qsort(), but I want to demonstrate how adding one level of indirection —the pointer to pointer— allows to insert elements smoothly, without testing for special cases.
// C pointer exercise: sort arguments
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
struct list
{
char *arg;
struct list *next;
};
int main(int argc, char *argv[])
{
// pointer to base, running pointer and pointer to pointer
struct list *base = NULL, *p, **pp;
for (int i = 1; i < argc; ++i)
{
struct list *new_entry = malloc(sizeof(struct list));
if (new_entry)
{
new_entry->arg = argv[i];
// find where to insert new entry
for (pp = &base; *pp; pp = &(*pp)->next)
if (strcasecmp(new_entry->arg, (*pp)->arg) < 0)
break;
// insertion in a simply linked list
new_entry->next = *pp;
*pp = new_entry;
}
}
// display and cleanup
for (p = base; p;)
{
struct list * tmp = p->next;
puts(p->arg);
free(p);
p = tmp;
}
return 0;
}
If condition inside the findset is not giving correct comparison. It is always shows not equal.
Where did I make a mistake?
#include<stdio.h>
struct node {
struct node *p;
int rank;
};
void makeset(struct node x) {
x.p = &x;
x.rank = 0;
}
void findset(struct node x) {
if (x.p == &x) {
printf("It worked bro\n");
}
}
int main() {
int nv, ne;
nv = 4;
ne = 5;
for (int i = 0; i < nv; ++i) {
struct node i;
makeset(i);
findset(i);
}
}
void findset(struct node x)
{
if (x.p == &x)
{
that x is a copy of the one passed in... x is always brand new and &x wont match any previous address.
Note that this is true not just of structs but all values...
int i = 3;
void f( int j)
{
// &j != &i
// j == i
// j and I have the same value, but different address
}
int main()
{
f(i);
}
There is no way your code will ever work. You ignore the fact that C uses pass by value -- meaning that when you pass a stuct node as a parameter to your function, (e.g. void makeset(struct node x)) the function receives a copy of the struct with its very own (and very different) address than the original struct in main().
So when you pass your struct to void findset(struct node x), there is no way if (x.p == &x) will ever test true -- because there is no requirement that the address of the copy of x received by void findset(struct node x) and stored in p is the same address as the copy of x that got passed to void makeset(struct node x).
Your second problem is your declare the same struct i 4 times in:
for (int i = 0; i < nv; ++i)
{
struct node i;
makeset(i);
findset(i);
}
You already have a variable i declared in your for loop. When you make the declaration struct node i;, you are not creating struct node 0;, struct node 1; ..., you are simply creating struct node i; 4 times. (no variable can be named a number or begin with a number in C) The i in your struct node declaration shadows the loop counter declaration of i. Add the warning -Wshadow to your compile string as a standard part of your compiler warnings.
What you need to do is declare an array of struct node if your want to be able to fill your nodes separately. For the purpose of this example, you could declare a struct with the same name 4-times - but that is rather limited to the use within your for loop (as your struct is declared within the for loop block, it is destroyed (the stack memory released for reused) each and every iteration of the loop. To prevent that from occurring, you can declare an array of 4 struct node before you enter your loop, e.g.
#include <stdio.h>
#define NNODES 4 /* if you need a constant, define one */
...
int main (void) {
struct node nodes[NNODES] = {{ .p = NULL }};
Next, to have any chance of findset ever being able to compare the original address of the struct node you pass as a parameter, you must pass the address of the struct, instead of the struct itself. That way, even though the function receives a pointer to a struct node, the value contained is the original address of the struct from the calling function (main() here)
So you need to change both function declarations to:
void makeset (struct node *x)
and
void findset (struct node *x)
You will also need to use the -> operator to access the members instead of the '.' operator.
Putting all the pieces together, you could do something similar to the following:
#include <stdio.h>
#define NNODES 4 /* if you need a constant, define one */
struct node {
struct node *p;
int rank;
};
void makeset (struct node *x)
{
x->p = x;
x->rank = 0;
}
void findset (struct node *x)
{
if (x->p == x)
printf ("It worked bro\n");
}
int main (void) {
struct node nodes[NNODES] = {{ .p = NULL }};
for (int i = 0; i < NNODES; i++) {
makeset (&nodes[i]);
findset (&nodes[i]);
}
}
(note: how the address of each struct node is passed to each function in main(), e.g. makeset (&nodes[i]);)
Example Use/Output
$ ./bin/struct_ptr_addr
It worked bro
It worked bro
It worked bro
It worked bro
It works now bro...
If you did really intend to declare a single stuct node in your for loop that is created and destroyed each iteration, then it works the same for a single struct as well -- you still have to pass the address of the struct to each function, e.g.
#include <stdio.h>
#define NNODES 4 /* if you need a constant, define one */
struct node {
struct node *p;
int rank;
};
void makeset (struct node *x)
{
x->p = x;
x->rank = 0;
}
void findset (struct node *x)
{
if (x->p == x)
printf ("It worked bro\n");
}
int main (void) {
for (int i = 0; i < NNODES; i++) {
struct node somenode = { .p = NULL };
makeset (&somenode);
findset (&somenode);
}
}
(the output is the same)
Hopefully, you now understand that when you pass a variable as a parameter, the called function receives a copy of the variable holding the original value. And, if you want to pass the address of the variable, then you have to pass the address as a pointer to insure that that original address is available within the called function (and any changes made visible back in the caller).
As the other poster said, you're passing in the value instead of the actual variable. The solution here is one of the reasons pointers are so powerful, you can just pass the pointer for the actual variable you want to change. For example:
void foo(){
int i = 8;
bar(&i);
}
int bar(int* i){
return *i * 2;
}
That should work better for you
I cannot understand the meaning of a C code about linked lists that is using double pointers. Here is the code I am reading
struct list
{
int value;
struct list *next;
};
//Insert an element at the begining of the linked list
void insertBegin(struct list **L, int val)
{
//What does **L mean?
//Memory allocation for the new element temp
struct list *temp;
temp = (struct list *)malloc(sizeof(temp));
//The new element temp points towards the begining of the linked list L
temp->next = *L;
//Set the beginning of the linked list
*L = temp;
(*L)->value = val;
}
void loop(struct list *L)
{
printf("Loop\n");
//Run through all elements of the list and print them
while( L != NULL )
{
printf("%d\n", L->value);
L = L->next;
}
}
struct list* searchElement(struct list *L,int elem)
{
while(L != NULL)
{
if(L->value == elem)
{
printf("Yes\n");
return L->next;
}
L = L->next;
}
printf("No\n");
return NULL;
}
int main()
{
struct list *L = NULL;
insertBegin(&L,10); // Why do I need
return 0;
}
What does **L in the insertElement mean and what is the difference between the **L and the *L in the loop function? Why in the main when struct list *L = NULL is declared I should call the function insertBegin with the argument &L and not a simple L?
I guess *L is a pointer towards the first node of the linked list while **L may point toward any element of the list. However, I am not sure this is correct.
Thank you for your help!
It means "pointer to a pointer". In C pointers are passed by value, so if you want to be able to modify a pointer passed to a function outside of that function, you have to pass a pointer to it. Passing the pointer will only pass another value for it, which will be modified in the function but will not reflect a change to the value outside of it. Passing as a pointer to pointer essentially allows you to modify the value at the address passed rather than just to modify the local.
Consider those two functions:
void foo(int * p, int * t) {
p = t;
}
void foo2(int ** p, int * t) {
*p = t;
}
And the code:
int a = 1, b = 2;
int * p = &a;
foo(p, &b);
// in foo *p == 2, but here *p is still == 1, because p didn't change, only the copy that was passed to foo changed
foo2(&p, &b); // now *p == 2, p was changed in foo2
The type **L is read as pointer to a pointer to L. So if you have a pointer to an L and takes its address, that is what you get. The pattern of **L in a function argument (in C) is usually used to implement an "out parameter" - a parameter the code can update. To insert at the beginning, you need to update the pointer to the head of the list - that is why that function takes a pointer to the head as a parameter. When assigning to *L, the function updates the parameter.
L stores address of the first link in the list. Thus:
*L is contents of the first link in the list, and
&L is the address of the variable that stores the address of the first link in the list.
In other words, your only way to allocate memory for and initialize a list by passing the argument into a function is by providing &L as an argument. If you pass L as an argument, the function will receive the address of the first link, whereas instead it needs a place where to store the address of the first link.
If you want a function to write to a parameter and have that new value reflected in the caller, then you must pass a pointer for that parameter:
void foo( T *p ) // for any type T
{
*p = new_value(); // write a new value to the thing p points to
}
void bar( void )
{
T var;
foo( &var ); // foo writes a new value to var
}
If we substitute T with a pointer type Q *, then the code is
void foo( Q **p ) // for any type Q
{
*p = new_value(); // write a new value to what p points to
}
void bar( void )
{
Q *var;
foo( &var ); // foo writes a new value to var
}
The semantics in both cases are exactly the same; we want foo to update the value stored in var through the pointer p. The only difference is that in the second case var already has a pointer type, so p has to be a pointer to that pointer type.
In the code you posted, the insertBegin function updates the value stored in L, which is a pointer to the head of the list. Since the variable L in main has type struct list *, the type of the parameter L in insertBegin needs to be struct list **.
The double pointer in insertBegin is for when you are changing the location of L from where ever L is to the node you are inserting. When calling the function you need &L because you need to pass it by reference because you are changing L
HERE IS MY INSTRUCTIONS FOR THIS FUNCTION: Here an unsigned integer listsize is passed to this function you are to create a link list of size listsize. This will be performed by repeated use of malloc and calling setData to initialize the data into the struct plane fields. Each time you place the process in the list you need to place it so the list is sorted by the field distance (in ascending order). you return the head of the list
struct plane* list_intialize(unsigned int num)
{
struct plane *ptr,*head;
int i=0;
ptr = (struct plane*) malloc(num * sizeof(struct plane));
for (i = 0; i < num; ++i)
setData(ptr+i);
return ptr;
}
This started as a function skeleton inside an already completed program....I'm to complete the function so that it creates a link list. The setData is given function that inserts data to the structure elements.....MY problem is that after I run the current function it only returns one plane with information instead of num amount....am I using setData wrong or should my current setup work
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifndef _MY_DEF_
#define _MY_DEF_
enum dir {NE=0, EN, NW, WN, SE, ES, SW, WS};
enum loc {LNE=0, LNW,LSE,LSW};
struct plane{
short flightCode;
long xCord;
long yCord;
double distance;
char direction;
enum dir flightPattern;
enum loc location;
struct plane *nextPlane;
};
#endif
struct plane* sortByDist(struct plane*);
struct plane * radarPrint(struct plane*head);
int checkPlane(struct plane *);
int checkForCollision(struct plane*);
void setData(struct plane *pLane);
You need to allocate your list by allocating each node. One way of doing that while chaining the list forward is the code below:
struct plane* list_intialize(unsigned int num)
{
struct plane *head, **pp = &head;
int i=0;
for (i=0; i<num; ++i)
{
*pp = malloc(sizeof(**pp));
setData(*pp);
pp = &(*pp)->nextPlane;
}
*pp = NULL;
return head;
}
How It Works
This uses a pointer-to-pointer to always hold the address of the location where the nextPlane dynamo node address is stored. It starts with the address of the head pointer. With each new node, pp is filled the address of that node's nextPlane member. Once finished, it holds the address of the last node's nextPlane pointer, which it sets to NULL. The first node, pointed to by head, is returned. (and yes, this works even if you passed num = 0 for the requested size, in which case you would get back zero nodes: i.e. NULL).
Note: Don't forget, you need to free each node when releasing the list, extracting a single node out, etc. For example, to delete an entire list:
void list_delete(struct plane **lst)
{
while (*lst)
{
struct node *victim = *lst;
*lst = victim->nextPlane;
free(victim);
}
}
Invoked like this:
struct plane *lst = list_initialize(N);
// use list.., maybe adding nodes, removing them, changing, etc...
list_delete(&lst);
How to print your list:
void list_print(const struct plane *lst)
{
while (lst)
{
// TODO: print list node pointed to by lst.
// Ex: (x,y) coords
printf("(%d,%d) ",lst->xCord, lst->yCord);
lst = lst->nextPlane;
}
printf("\n");
}
You are not setting the links between the objects. In the for loop, you need:
ptr[i]->nextPlane = ptr[i+1];
At the end of the loop, make sure the last object points to NULL.
ptr[i-1] = NULL;
typedef struct node
{
struct node *leftChild, *rightChild;
int value;
} bst;
void insert(bst* b, int i)
{
b=malloc(sizeof(b));
b->value=i;
b->leftChild = NULL;
b->rightChild = NULL;
printf("[%i]",b->value);
return;
}
main()
{
bst* b;
insert(b,5);
printf("[%i]",b->value);
}
The second printf causes a Segmentation Fault, commenting it out it works fine. What am I doing wrong here (Ignore the meanings of the function names i.e. that the insert is an insert function for the bst)? Shouldn't bst persist in it's setup outside of the insert function?
You need to pass the pointer by reference to change where it points.
// just add this & here in the function definition.
// That's the only change in all your code (for c++)
void insert(bst * &b, int i)
Or in C, a pointer pointer
void insert(bst ** b, int i)
{
*b=malloc(sizeof(*b));
(*b)->value=i;
(*b)->leftChild = NULL;
(*b)->rightChild = NULL;
printf("[%i]",(*b)->value);
return;
}
Note the changes to dereference the pointer pointer.
When you call this function, you'll need to take the address of your bst *:
insert(&b,5);
The problem is that b in main points to an invalid memory. The b doesn't get changed by insert because insert uses a copy of the pointer. You have to options to solve this:
Make "insert" take a pointer to pointer
Allocate the memory before entering "insert"
Because the first one is harder to read (and understand), I'd prefer the second one. But it depends on you what variant you choose.
Memory allocation before insert:
typedef struct node
{
struct node *leftChild, *rightChild;
int value;
} bst;
void insert(bst* b, int i)
{
// No malloc here
b->value=i;
b->leftChild = NULL;
b->rightChild = NULL;
printf("[%i]",b->value);
return;
}
main()
{
bst* b = (bst *)malloc(sizeof(bst)); // This line has changed
insert(b,5);
printf("[%i]",b->value);
}
The variant with a double pointer:
typedef struct node
{
struct node *leftChild, *rightChild;
int value;
} bst;
void insert(bst** b, int i)
{
*b = (bst *)malloc(sizeof(bst)); // This line has changed
(*b)->value=i;
(*b)->leftChild = NULL;
(*b)->rightChild = NULL;
printf("[%i]", (*b)->value);
return;
}
main()
{
bst* b;
insert(&b,5); // Now b is changed
printf("[%i]",b->value);
}
Side note 1: you also have the malloc() incorrect - you should put use sizeof(bst) instead of sizeof(b) as the size. This is because sizeof(b) == sizeof(bst *) == size of an address, which is almost certainly not what you want.
Side note 2: do not forget to call free(b) at the end to avoid memory leaks.
Side note 3: check that malloc() doesn't return NULL. A rare case but a good program should expect that.
Since C does pass-by-value for arguments, the pointer being referenced inside insert() is a copy of the original b. The memory gets allocated to the variable b inside the function, but not to the variable in the main()function.
for eg.
# In main
b<main> = 0xOrigLoc
b<insert> = undefined
# In insert (before malloc)
b<main> = 0xOrigLoc
b<insert> = 0xOrigLoc
# After Malloc
b<main> = 0xOrigLoc
b<insert> = 0xNewLoc
Notice how b<main> remains untouched. You are only tweaking the copy of b inside the function.
The solution is to use a pointer to a pointer as described by the previous solution.
Rather than change the value, return the new value of b
bst* insert(bst* b, int i)
{
if (b == NULL)
{
bst* result = (bst*)malloc(sizeof(bst));
result->value=i;
result->leftChild = NULL;
result->rightChild = NULL;
printf("[%i]",b->value);
return result;
}
if (i < b->value)
b->left = insert(b->left, i);
else
b->right = insert(b->right, i);
return b;
}
int main()
{
bst* b = NULL; // Initialise it to empty.
b = insert(b,5);
printf("[%i]",b->value);
}
Well one problem is you're not typecasting your pointer.
The line:
b=malloc(sizeof(b));
Should be:
b=(bst*)malloc(sizeof(b));
Your code gives me an error when I compile it in gcc.
This is how to identify and fix errors in the future:
Testing in GDB:
Full code:
#include <malloc.h>
#include <stdio.h>
typedef struct node
{
struct node *leftChild, *rightChild;
int value;
} bst;
void insert(bst* b, int i)
{
b=(bst*)malloc(sizeof(b));
b->value=i;
b->leftChild = NULL;
b->rightChild = NULL;
printf("[%i]",b->value);
return;
}
main()
{
bst* b;
insert(b,5);
printf("[%i]",b->value);
}
Compiled with
%g++ -g main.cc
Ran with
%gdb a.out
GDB commands:
b main.cc:211
run
print b
(output is: 0x0)
step
step
print b
(output is: 0x4f60010)
step
step
step
step
step
print b
(output is: 0x0)
quit
This clearly indicates that your variable is getting deallocated when the function leaves its scope.
Changing the code to:
#include <malloc.h>
#include <stdio.h>
typedef struct node
{
struct node *leftChild, *rightChild;
int value;
} bst;
void insert(bst* b, int i)
{
b->value=i;
b->leftChild = NULL;
b->rightChild = NULL;
printf("[%i]",b->value);
return;
}
main()
{
bst* b;
b=(bst*)malloc(sizeof(bst));
insert(b,5);
printf("[%i]",b->value);
free(b);
}
and rerunning gdb with the following commands:
b main.cc:21
run
s
(short for step)
print b
(output: 0x1aab010)
s
s
s
s
s
s
print b
(output: 0x1aab010)
Your problem is clearly the scope of the allocation. Moving the allocation to main fixes this.
Yay your program now works!
This should give you insight into how to use the debugger to solve these kinds of simple errors in the future.
Edit:
As one op pointed out, your underlying problem is that pointers passed to functions in c are treated as local objects, so when you exit the function, any allocated memory to single pointers is tossed in the bitbucket.
Double pointers allow you to actually allocate within functions, you just have to be careful to dereference them as necessary. So your working code could also be:
#include <malloc.h>
#include <stdio.h>
typedef struct node
{
struct node *leftChild, *rightChild;
int value;
} bst;
void insert(bst** b, int i)
{
(*b)=(bst*)malloc(sizeof(bst));
(*b)->value=i;
(*b)->leftChild = NULL;
(*b)->rightChild = NULL;
printf("[%i]",(*b)->value);
return;
}
main()
{
bst* b;
insert(&b,5);
printf("[%i]",b->value);
free(b);
}
bst* b; declares a pointer... but doesn't allocate the actual structure.
allocate and initialize b and you'll be onto your next step.
This is slightly a style discussion but your main should look either like this.
main()
{
bst *b;
b = (bst*)malloc(sizeof(bst));
/* more initialization */
insert(b, 5);
free(b);
}
or like this
main()
{
bst *b;
bst_new(&b);
insert(b, 5);
bst_free(&b);
}