Passing pointers into another function in C - c

Say I have a variable
int * foo;
I pass this variable into
func(int *x)
{
*x = bar;
}
However, this does not work. However, if I put a non-pointer (say change it to int foo;) and directly put the address in, this works.
Why doesn't my first case work?
Thanks!

Your code is doing exactly what you are telling it too. However, int *foo does not allocate any storage. The pointer is simply a handle to a memory address. In this case, it is arbitrary and results in undefined behavior. Try the following instead.
void func(int *x) {
*x = 42;
}
int main(int argc, char** argv) {
int *foo;
int storage;
foo = &storage;
func(foo);
printf("%d\n" storage);
return 0;
}
foo is simply a pointer to storage which is allocated on the stack by the runtime. You are just as well off using foo(&storage) in this case.

By declaring int * foo you've only created a pointer. foo is not actually pointing at anything yet - it's uninitialised. You might even get a segmentation fault from code like that, as the pointer could point outside of program memory. If you do:
int * foo = (int *)malloc(sizeof(int));
You will have initialised the pointer, malloc allocates some memory from the heap of the size passed to it. You can also do:
int bar = 0;
int * foo = &bar;
Which will make foo a pointer to bar (& returns the address of the variable).

You should do something like this
int bar = 235; // any value you want
void func(int *x)
{
*x = bar;
}
int main()
{
int *foo;
foo = (int*)malloc(sizeof(int));
func(foo);
printf("%d", *foo);
free(foo);
return 0;
}

Related

Passing structs into function by address vs a pointer in C

I was hoping someone could help me figure out why one version of the below code works, while the other doesn't. Below I've included the initArray method, stored in "worksheet.c". The function is accessed in main, both versions are given below.
void initArray(struct dynArray *a) {
a->data = malloc(10 * TYPE_SIZE);
assert(a->data != 0);
a->size = 0;
a->capacity = 10;
}
This works. I create a dynArray struct and pass it to initArray by reference.
#include "worksheet0.h"
#include <stdio.h>
int main(void)
{
struct dynArray b;
initArray(&b);
return 0;
}
This fails with a seg fault. I thought that passing b here would be the same as passing the struct by reference.
int main(void)
{
struct dynArray *b = NULL;
initArray(b);
return 0;
}
Because in the second case there is no memory allocated to which the struct pointer points to. It is simply a pointer having the value NULL. On your case by dereferencing the value NULL you have invoked undefined behavior.
It would work if you allocate memory, make changes to it and then return it's value. [But then you have to return the address of the allocated memory.] OR you can pass the address of the pointer variable and allocate memory to which dereferenced pointer (here the pointer has type struct dynAray**) would point to and make changes to it.
Let's be more clear now slowly:
Why the first case works? You have a struct dynArray variable whose address you have passed into the function and then you have accessed the content of that address - wait! that means you have accessed the struct dynArray variable itself and made changes to its member variables. Yes that is what exactly happened in the first case.
In the second case, you have a pointer to struct dynArray. And then you passed it - de-referenced it. Where was it pointing to? Is it some struct dynArray variable's address that it contained? No. It was NULL. So it is wrong if you expect it to work.
The second would work - but you have to change things a bit! Let's see how:
struct dynArray* initArray() {
struct dynArray* a = malloc(sizeof *a);
assert(a != NULL);
a->data = malloc(10 * TYPE_SIZE);
assert(a->data != 0);
a->size = 0;
a->capacity = 10;
return a;
}
And in main()
struct dynArray* b;
b = initArray();
You don't even need to pass the pointer variable. That would be meaningless if you want to do it like this.
And you know you can also pass the address of the pointer variable so that you can make changes to it -
void initArray(struct dynArray** a) {
*a = malloc(sizeof **a);
assert((*a) != NULL);
(*a)->data = malloc(10 * TYPE_SIZE);
assert((*a)->data != 0);
(*a)->size = 0;
(*a)->capacity = 10;
}
For this in main() you would call it like this
struct dynArray* b;
initArray(&b);
In the first example a pointer holding the address of an actual struct is passed to the function. But, in the second example the pointer b does not point to a struct. Instead, this pointer is initialized to NULL, and when this null pointer is dereferenced in the initArray() function, undefined behavior ensues.

function with void double pointer output

A function returns a void double pointer containing a pointer to a float array, how can i access the output data?
void **pointer;
// function(void **ptr)
function(pointer);
This pointer points has to point to a float type pointer.
float *coords;
coords = (float*)malloc(3*500*sizeof(float)); //I know the amount of memory to be allocated
How can I read the data from this void double pointer? I'm pretty confused.
Your function prototype is not with respect to what you want to achieve. If you want your function to allocate memory and send its reference back to the main then your function will look like this (considering you want to pass double pointer) :
void function(void ***ptr)
{
float *coords;
coords = (float*)malloc(3*500*sizeof(float));
*ptr = (void **) &coords;
//do something
return;
}
main()
{
void **pointer;
function(&pointer);
/* Accessing first member of array allocated in function */
printf("%f", (*((float **)pointer))[0]);
}
If this is the objective, there is simpler way :
void function(void **p)
{
float *coords;
coords = (float*)malloc(3*500*sizeof(float));
*p = coords;
return;
}
main()
{
void *pointer;
function(&pointer);
printf("%f", ((float*)pointer)[0]);
}
Hope this helps.
Please check your code. What you are posting is nonsense - you have an uninitialised variable and pass it to a function. That's undefined behaviour and can crash or worse before the function even starts executing.
I think you are confused by what you call a "double pointer". There is no such thing as a "double pointer". A pointer points to something, it doesn't double-point. A pointer might point to an int (an int*), or to a struct T (struct T*) or to a float* (a float**). In the float** there are two *'s, but that doesn't make it a "double pointer". It is an ordinary pointer that happens to be pointing to something that is itself a pointer.
Pointers as function parameters are most often used so that the function can return more than one value. Say a function get_width_and_height returning to ints:
void get_width_and_height (int* width, int* height) {
*width = 10;
*height = 20;
}
int x, y;
get_width_and_height (&x, &y);
Now with that example in mind, how would you write a function that returns two int and one float* ?
I am going to have to make a few assumptions here as the question is unclear
I am going to assume that you call the function thus:
void **pointer;
function(pointer);
Then want to access the output, so do
flow *coord = (float *) *pointer;
Then you are home free

usage of double pointers as arguments

Please find the code snippet as shown below:
#include <stdio.h>
int My_func(int **);
int main()
{
int a =5;
int *p = &a;
My_Func(&p);
printf("The val of *p is %d\n,*p);
}
void My_Func(int **p)
{
int val = 100;
int *Ptr = &val;
*p = Ptr;
}
How does by using a double pointer as a argument in my_Func function and making change of value reflects the same in the main function but if we use a single pointer in My_Func does not change the value in main?Please do explain me with examples if possible
Advanced thanks
Maddy
int **p is a pointer to a pointer-to-int. My_Func(int **p) works by changing the value of integer that the pointer-to-int points to i.e. int a.
Without changing the implementation, the function will not work with a pointer-to-int parameter int *p as there is a second level of indirection. In addition, you're setting the value to a local variable that is created on the stack. When the function is completed the memory used for the variable will be reclaimed, therefore making the value of a invalid.
void My_Func(int **p)
{
int val = 100; // Local variable.
int *Ptr = &val; // This isn't needed.
*p = Ptr;
} // val dissapears.
Remove the second level of indirection and copy val by value instead of pointing to it:
#include <stdio.h>
void My_Func(int *p)
{
int val = 100;
*p = val;
}
int main(void)
{
int a = 5;
My_Func(&a);
printf("The val of a is %d\n", a);
return 0;
}
In short, in C when you pass something as a parameter, a copy will be passed to the function. Changing the copy doesn't affect the original value.
However, if the value is a pointer, what it points to can be changed. In this case, if you want to affect the pointer, you need to pass a pointer to it down to the function.
Use it in the function declaration:
void func(int *p)
{
int val =100;
int *temp=&val;
p=temp;
}
p starts pointing to another address i.e. address of val. So it will print the value 100.
Important note: Try it in your downloaded compiler (always in case of pointers) not in the online compiler. The online compiler doesn´t keep track of lost addresses in stack.
You are assigning the address of local variable, which will soon disappear when My_Func returns. You can use following in your code. However you can do the same thing just by using single pointer, double pointer is not required in this example.
void My_Func(int **p)
{
int val = 100;
int *Ptr = &val;
**p = *Ptr;
}

passing a pointer as argument to a function in C

Something I stumbled upon and made me wonder.
Why does this work?
void foo (int* a)
{
int x = 3;
*a = x;
}
int main()
{
int a;
foo(&a);
return 0;
}
But this causes a segmentation fault (both on Visual Studio 2008 and gcc)?
void foo (int* a)
{
int x = 3;
*a = x;
}
int main()
{
int* a;
foo(a);
return 0;
}
Is it something defined in the language or just an implementation issue?
When you declare
int* a;
You are declaring a pointer variable a but you are not making it point to anything. Then in the function, you do
*a = x;
Which dereferences the pointer and tries to assign what it points to the value of x. But since it doesn't point to anything, you get undefined behaviour, manifested in a segmentation fault.
You should do this:
int i; // the actual integer variable
int* a = &i; // a points to i
The difference between that and the first one is that int a; declares a real integer variable, then you take its address with &a and passes it to the function. The pointer a inside the function foo points to the variable a in main, and so dereferencing it and assigning to it is perfectly fine.
int a;
Assigns memory as soon as you declare it but this not the case with int *a;
int *a;
is pointer declaration (MEMORY not yet allocated for that).
int *a = (int*)malloc(sizeof(int)); // allocate memory

Scope of malloc used in a function

When a function returns, is the memory allocated via malloc freed? Or can it still be accessed in the main() function using pointers?
eg.
void function(int *a)
{
a=(int *)malloc(sizeof(int));
*a=10;
}
int main()
{
int *num;
function(num);
printf("%d",*num);
return(0);
}
Can the integer stored in a be accessed by main() here?
No, the memory allocated with malloc is not freed when you leave the scope/return from the function.
You're responsible for freeing the memory you malloc.
In your case though, the memory is NOT accesible in main(), but that's because you only deal with a local variable.
void function(int *a)
{
a=(int *)malloc(sizeof(int));
Here, a is a local variable within function . Pointers are passed by value in C, so a receives a copy of the pointer in main when you do function(num); main() does not see that you assign to that local copy of the pointer.
You have to do either:
void function(int **a)
{
*a= malloc(sizeof(int));
**a=10;
}
int main()
{
int *num;
function(&num);
printf("%d",*num);
free(num);
return(0);
}
or
int* function(void)
{
int *a= malloc(sizeof(int));
*a=10;
return a;
}
int main()
{
int *num;
num = function();
printf("%d",*num);
free(num);
return(0);
}
malloc()ed memory is only freed when you call free() on it. It can be accessed by anybody with a valid pointer to it until that time.
No. You are passing the pointer numby value, hence the changes made by the function will not be reflected in main. So effectively there is no way to access/free the allocated memory from main
To fix this you can pass the address of num or return a from function and collect the returned value in num
Memory is not freed. Any function can allocate memory and any other can deallocate it. It's a real mess if you're not super-finicky, until... someone invented the Garbage Collection.
malloc is working fine (though you will have to call free() on the pointer it returns). The problem here is that you aren't returning a pointer to the memory it allocated.
"int * a", your parameter to function() is the address of an integer. The usual way to return that would be to rewrite your function as follows:
int * function()
{
int * a = (int *)malloc(sizeof(int));
*a = 10;
return a;
}
To return it via a parameter, you need to return the address of the pointer:
// pp points to a pointer
void function( int ** pp )
{
// Assign allocated memory to the thing that pp points to
*pp = (int *)malloc( sizeof( int ) );
// Get the thing pp points to -- a pointer.
// Then get the thing which THAT pointer points to -- an integer
// Assign 10 to that integer.
**pp = 10;
}
void main()
{
int * p = NULL;
function( & p );
printf( "%d\n", *p );
free( p );
}
And now you know why they invented C#.
Here's a way to rewrite your allocation thing so it's more clear:
void function( int ** pp )
{
int * newmemory = (int *)malloc( sizeof( int ) );
// Assign 10 to the integer-sized piece of memory we just allocated.
*newmemory = 10;
// Assign allocated memory to the thing that pp points to.
*pp = newmemory;
}
You can store the direct address of the allocated memory in a list container then create a function to loop, access each address into a free function, and then pop out the address. You can insert the address directly into the free function like free(myaddresslist.front()); myaddresslist.pop_front(); . This is a quasi way of doing your own garbage collection without having to change your entire project to GC based languages. Use myaddresslist.size() to make sure you don't call free() on an empty field (resulting in a crash) and to determine the number of loops to take.

Resources