How do you properly allocate a struct inside a function? [duplicate] - c

This question already has answers here:
How to malloc inside a function and return pointer in C?
(3 answers)
Closed 7 years ago.
I have this code which is where I've narrowed down the problem. When I step through with the debugger it seems to be fine but as soon as it leaves the function, freeCount loses the value assigned to it. It is supposed to be 100, and until the last } it shows it assigned the value fine but as soon as the function breaks it goes back to some 16 digit value. Can anyone point out my error?? much appreciated!
void initializeTree(TREE* empList)
{
empList = (TREE *)malloc(sizeof(TREE));
int i;
for (i = 1; i <= maxEmp; i++)
{
time_t seed = time(null);
empList->freeList[i] = (int)(rand() % seed);
}
empList->freeCount = maxEmp;
empList->parent = null;
empList->root = null;
}

It's because in C arguments to functions are passed by value, which means they are copied. So when you pass a pointer to a function, the functions receives a copy of the pointer, and as you know changing a copy will not change the original.
C doesn't have argument passing by reference, but it can be emulated using pointers. So to pass a pointer by reference you need to pass a pointer to the pointer.
void initializeTree(TREE** empList)
{
*empList = malloc(sizeof(TREE));
...
(*empList)->freeCount = maxEmp;
...
}
To call this function you need to use the address-of operator &:
TREE *empList;
initializeTree(&empList);
Another alternative is to return the pointer:
TREE* initializeTree(void)
{
TREE* empList = malloc(sizeof(TREE));
...
return empList;
}

You are overwriting the value of empList in your function but it does not reach the caller. What you actually need to do is to pass in a pointer to a pointer of tree:
void initializeTree(TREE** empList)
{
*empList = (TREE *)malloc(sizeof(TREE));
[...]
}
You can also find more information (and other options) here.

Related

How to use pointers when calling a function [duplicate]

This question already has answers here:
Changing address contained by pointer using function
(5 answers)
Closed 5 years ago.
I have some issue with programming in C. I have a structrure, that goes like
typedef struct Hash_Funct{
char* name;
Var_Table * List_of_Variables; ///pointer to list of variables
} Hash_Funct;
And in certain point of code, I want to inicialize the structure with:
Hash_Funct tmp = (Hash_Funct*) malloc(sizeof(Hash_Funct));
tmp->name=name;
Init_ID_Table(tmp->List_of_Variables);
Where the Init_ID_Table(); is defined as:
void Init_ID_Table(Var_Table *table){
table = (Var_Table*) malloc ( sizeof(Var_Table) );
for(int i=0; i< SIZE;i++){
(*table)[i] = NULL;
}
}
However, at the end of this code, it doesnt seems that the Init_ID_Table() had any affect on the * List_of_Variables pointer (which should now point onto a table of size SIZE and have all its elements set to NULL). Can anyone at least tell me what is going on if not how to change it to work as expected?
Thank you very much,
Adam
Variables are passed by value, assigning to the parameter variable in the function has no effect on the caller's variable.
You need to pass a pointer to the struct member, and indirect through it to modify the caller's variable.
void Init_ID_Table(Var_Table **table) {
Var_Table *temp_table = malloc ( sizeof(Var_Table) );
for (int i = 0; i < SIZE; i++) {
temp_table[i] = NULL;
}
*table = temp_table;
}
Then you would call it this way:
Init_ID_Table(&(tmp->List_Of_Variables));

Unable to modify pointer variable passed as argument to a function

I have this function
int rt_exist(struct route_entry* prev_rte) {
prev_rte = rte_head; //This doen't assigns rte_head to prev_rte
return 0;
}
where rte_head is an initialized struct route_entry* pointer variable.
But in the above case "prev_rte" is not assigned the value of rte_head.
By the way ,I if I do something like this
int rt_exist(struct route_entry* prev_rte) {
struct route_entry* rte_new;
rte_new = rte_head; //But this can
return 0;
}
The above assignment occurs smoothly . The problem arises when pointer variable is passes as function argument.
It's a weird question with little details ,but can someone point me to a possible direction or something wrong I might be doing.
Consider this:
void foo (int j)
{
j = 7;
}
foo (8);
What do you expect to happen here? A function can't change a value in the caller this way.
What should happen here:
rt_exist (NULL);
For C++, you can use references:
int rt_exist(struct route_entry*& prev_rte) {
prev_rte = rte_head; //This doen't assigns rte_head to prev_rte
return 0;
}
For C, you need to pass a pointer to the thing you want to change:
int rt_exist(struct route_entry** prev_rte_ptr) {
*prev_rte_ptr = rte_head; //This doen't assigns rte_head to prev_rte
return 0;
}
Yes! in first case you are using temporary portion of a stack. But in the second case you are using allocating. Which means that you are using a portion of memory which is from heap. It will obviously affect the value. This is like a new variable in a new block. In this scope it will have the assigned value.
But in rt_exist the copy of the variable is passed. So any change in that will not affect the actual one. But you can pass it's address and change it easily like this.
int rt_exist(struct route_entry** prev_rte)
{
*prev_rte = rte_head; //This does assign rte_head to prev_rte.
return 0;
}

Update (int) variable in C inside a function [duplicate]

This question already has answers here:
How to change a variable in a calling function from a called function? [duplicate]
(3 answers)
Closed 8 years ago.
I'm trying to write a function that changes screen in my simple C snake game.
main(){
int stage = 0;
...
..
.
while(stage!=0){
//if snake hits wall
changeStage(stage);
}
}
function:
void changeStage(int stage){
stage = 1;
}
This code does not update the code, it will keep on running.
What is wrong with my code?
stage is passed by value to changeStage. stage = 1 only changes the local value of stage in changeStage, not the value of stage in main. You have to pass a pointer instead:
while (stage != 0) {
changeStage(&stage);
}
void changeStage(int *stage) {
*stage = 1;
}
C is a pass by value language. The simplest approach to accomplish what you want is to pass a reference to the variable you need to change. For example:
void changeStage(int *stage){
*stage = 1;
}
main(){
int score = 0;
int stage = 0;
...
..
.
while(stage!=0){
//if snake hits wall
changeStage(&stage);
}
}
Note: You may need to read up on pointers to fully understand the code if you are just beginning with C programming. In the example code, instead of passing the value of 'stage', you pass the location where the value of 'stage' is stored. The function can then modify the contents in the location.
C function arguments are pass-by-value. This means that instead of passing a reference to stage you are passing the value stored in it. The update you do the in changeStage function then only applies to the copy that has been made.
If you want to update a variable in another function, you will need to pass a pointer to it.
void changeStage(int* stage_p){
*stage_p = 1;
}
int main() {
//...
while(stage!=0){
//if snake hits wall
changeStage(&stage);
}
}
&stage says to take the address of stage and pass that to the function. The stage_p argument will then point to the int in the main.
*stage_p causes it to use the value pointed to by stage_p, which is stage in the main in your case.
Further reading
You are not modifying the original stage variable, but only modifying an local copy inside changeStage function.
You need to use a pointer:
void changeStage(int* stage)
{
*stage = 1;
}
using the function:
while (stage != 0)
{
// if snake hits wall
changeStage(&stage);
}
You need learn more basic concepts of C language. Pointer is an very important feature in C language.
Correct, you need to pass the pointer if you wish to change the value of the variable in main() or you can create it as global variable, that way it's accesable both in functions and in main.
static int stage = 0;
void changeStage(){
stage = 1;
}
main(){
int score = 0;
...
..
.
while(stage!=0){
//if snake hits wall
changeStage();
}
}

How do you pass a struct Pointer in C?

I am a little confused by how pointers are passed in functions by reference?
For instance, here's some code that I have written
(I didn't copy the entire function, just the part of it that is relevant)
metadata * removeBlock(metadata *first)
{
metadata *temp = first;
if(first == NULL || first -> prev == NULL)
{
first -> in_use = 1;
first = NULL;
return temp;
}
}
What I want is that when the function returns, the original value passed in should be set to NULL.
Here is how I call the function, (this line of code will pull a metadata structure from a region in heap, it works correctly, I have debugged and made sure that after this, struct really points to a valid metadata struct)
metadata *strct = ((metadata *)ptr - sizeof(metadata));
removeBlock(strct);
However, after this method returns, strct is still the same value it was before I had passed it in the function. I tried passing in &strct, but that just threw an invalid cast exception. What is the best way to pass in the struct as an argument?
Thankyou.
I don't think what you want is a good design - if the user of your function wants the pointer set to null (why?) it would make sense to reset the value using the return value from your function.
Anyway, you'll want a pointer-to-a-pointer, like so:
metadata* removeBlock(metadata** first) {
metadata* temp = *first;
if( temp == NULL ) return temp;
if( temp->prev == NULL ) {
temp->in_use = true;
*first = NULL;
}
return temp;
}
metadata* strct = ((metadata*)ptr - sizeof(metadata));
removeBlock(&strct);
As #SheerFish said, all we have in C is pass-by-value. However, one can simulate pass-by-reference with a pointer.
void func(struct foo **fooptr) { *fooptr = 0; }
int main(int argc, char **argv) { struct foo *fooptr; func(&fooptr); }
This is passing a pointer ptr to the variable's value (never mind if that value was a pointer), allowing the function to play with the original value with *ptr. This technique is sometimes called pass-by-address, and is the closest C has to pass-by-reference.
If you pass by 'reference in C', you're going to need to keep in mind referencing and de referencing via ->/** and *. This bit of code I wrote may help you a bit
int delete_node(struct node** head, int target)
{
if(*head == NULL)
return 0;
if((*head)->data == target)
{
temp = *head;
*head = (*head)->next;
free(temp);
return 1;
}
}
Function call:
delete_node(&head, data)
You're working with direct memory pointer manipulation. You're tossing the location of the struct in memory, de referencing it, then changing the value at that memory location.
I didn't read all of the details, but this part jumped out as incorrect:
(metadata *)ptr - sizeof(metadata)
Pointer arithmetic is done in the units of the type, whereas sizeof gives you measurements in bytes.
So I suspect what you're trying to say is:
(metadata *)(((char*)ptr) - sizeof(metadata))
This is also making some assumptions about the machine you're running on, i.e. metadata may need to be padded to ensure that the fields are properly aligned for this use. If sizeof(metadata) is not a multiple of the word size, this will fail on a lot of architectures. (But x86 will let it slide, albeit with performance costs and some implications like atomic ops not working on the fields.)
pointers are passed by value. anything in c is passed by value. so in order to change the pointer passed to the function, it should receive metadata **first.
besides, you should use
metadata *strct = ((metadata *)ptr - 1);
as pointer arithmetic is done with multiples of sizeof(*p). so this is equivalent to
metadata *strct = ((metadata *)((char*)ptr - sizeof(metadata)));

why can't i free the memory?

I wrote a simple counter structure in C:
typedef struct{
int value;
}Counter;
then, I wrote some simple implementations:
void createCounter(Counter *dCount)
{
dCount = (Counter*)malloc(sizeof(Counter));
dCount->value = 0;
}
void FreeResource(Counter *dCount)
{
free(dCount);
}
now in the main, i wanted to free the pointer i created and it complained that the pointer being freed was not allocated.I am looking at the code and I thought I allocated memory for it when I called the createCounter() function?
int main()
{
Counter m;
CreateCounter(&m);
FreeResource(&m); //run time error given here..
return 0;
}
You are trying to pass the address of a variable allocated in stack and then trying to assign an address allocated by malloc to it which won't get reflected in the caller. So, when you try to free it, you are effectively passing a stack variable's address to free due to which you get undefined behavior.
Change the function
void createCounter(Counter *dCount)
{
dCount = (Counter*)malloc(sizeof(Counter));
dCount->value = 0;
}
as
void createCounter(Counter **dCount)
{
*dCount = (Counter*)malloc(sizeof(Counter));
(*dCount)->value = 0;
}
In your case, the pointer gets passed by value and the new memory address allocation doesn't reflect in the caller.
The main function must be changed as:
int main()
{
Counter *m;
CreateCounter(&m);
FreeResource(m); //run time error given here..
return 0;
}
dCount = (Counter*)malloc(sizeof(Counter));
There are multiple problems:
dCount = ... has absolutely no effect for the caller., i.e. the pointer is unchanged.
You passed a pointer to an already allocated structure, you don't need to malloc anything
You're trying to free something (&m) you didn't obtain from malloc
The only sane suggestion at this point is to review a chapter on pointers.
The problem is that in CreateCounter the variable dCount is a local variable. That means changes to the variable won't be visible when the function returns.
There are two common solutions to this:
Return the pointer:
Counter *CreateCounter()
{
Counter *dCounter = malloc(sizeof(Counter));
dCounter->value = 0;
return dCounter;
}
Pass the argument as a reference, i.e. a pointer to the pointer:
void CreateCounter(Counter **dCounter)
{
*dCounter = malloc(sizeof(Counter);
(*dCounter)->value = 0;
}
And call it as this:
Counter *m;
CreateCounter(&m);

Resources