Allocating memory for a pointer passed from another function

A

Adam Baker

I'm sure this is a fairly basic question. I want a pointer in main()
to be passed to a function, and to allocate memory for the pointer in
the function, and then have it available to main after.

This does not work:

#include <stdio.h>

void func(float *a)
{
a = malloc(5*sizeof(float));
*(a+5) = 15.0f;
}

int main()
{
float *ptr;
func(ptr);
printf("%g\n",*(ptr+5)); // prints something other than 15
return 0;
}

This sort of makes sense, since I'm passing ptr as an argument. Is
there a way to pass ptr so that it behaves as expected? Or do I have
to do this?

#include <stdio.h>

float* func()
{
float *a = malloc(5*sizeof(float));
*(a+5) = 15.0f;
return a;
}

int main()
{
float *ptr;
ptr = func();
printf("%g\n",*(ptr+5));
return 0;
}


Thanks,
Adam
 
R

Richard Heathfield

Adam Baker said:
I'm sure this is a fairly basic question. I want a pointer in main()
to be passed to a function, and to allocate memory for the pointer in
the function, and then have it available to main after.

This does not work:

#include <stdio.h>

void func(float *a)
{
a = malloc(5*sizeof(float));
*(a+5) = 15.0f;
}

int main()
{
float *ptr;
func(ptr);
printf("%g\n",*(ptr+5)); // prints something other than 15
return 0;
}

No, it doesn't.

Several corrections are required. Firstly, add:

#include <stdlib.h>

so that you get a proper prototype for malloc.

Secondly, if you want to call a function in order to modify the value of an
object, you must pass the address of that object. In this case, the object
whose value you wish to modify is ptr, so you must pass &ptr to func, and
pick it up as float **, like this:

#include <stdio.h>
#include <stdlib.h>

void func(float **a)
{
*a = malloc(6 * sizeof **a); /* changed from 5 because see below */
if(*a != NULL)
{
(*a)[5] = 15.0f; /* 0-based indexing: 0 1 2 3 4 >>5<<, the SIXTH
element, not the fifth, so you need memory for
six, not five, elements. */
}
}

int main()
{
float *ptr = NULL; /* Indeterminate pointer values cause trouble */
func(&ptr); /* note the ampersand */
if(ptr != NULL)
{
printf("%g\n",*(ptr+5));
free(ptr);
ptr = NULL;
}
return 0;
}
float* func()
{
float *a = malloc(5*sizeof(float));

Make that 6, not 5.
*(a+5) = 15.0f;
return a;
}

That way works too, yes.
 
F

Francine.Neary

I'm sure this is a fairly basic question. I want a pointer in main()
to be passed to a function, and to allocate memory for the pointer in
the function, and then have it available to main after.

This does not work:

#include <stdio.h>

void func(float *a)
{
a = malloc(5*sizeof(float));
*(a+5) = 15.0f;

}

int main()
{
float *ptr;
func(ptr);
printf("%g\n",*(ptr+5)); // prints something other than 15
return 0;

}

This sort of makes sense, since I'm passing ptr as an argument. Is
there a way to pass ptr so that it behaves as expected?

Function arguments are always passed by value in C.

You can pass a pointer to a pointer instead:

#include <stdio.h>
#include <stdlib.h>

void func(float **a)
{
*a = malloc(6 * sizeof **a);
if(*a)
*(*a+5) = 15.0f;
else {
fputs("No memory\n", stderr);
exit(EXIT_FAILURE);
}
}

int main(void)
{
float *ptr;
func(&ptr);
printf("%g\n", *(ptr+5));
free(ptr);
return 0;
}

(Note some other subtle difference from your code, too.)
 
D

Default User

Adam said:
I'm sure this is a fairly basic question. I want a pointer in main()
to be passed to a function, and to allocate memory for the pointer in
the function, and then have it available to main after.

This does not work:

#include <stdio.h>

void func(float *a)
{
a = malloc(5*sizeof(float));
*(a+5) = 15.0f;
}

int main()
{
float *ptr;
func(ptr);
printf("%g\n",*(ptr+5)); // prints something other than 15
return 0;
}

This is essentially FAQ 4.8:

<http://c-faq.com/ptrs/passptrinit.html>




Brian
 
C

CBFalconer

Adam said:
I'm sure this is a fairly basic question. I want a pointer in main()
to be passed to a function, and to allocate memory for the pointer in
the function, and then have it available to main after.

This does not work:

#include <stdio.h>

void func(float *a) {
a = malloc(5*sizeof(float));
*(a+5) = 15.0f;
}

int main() {
float *ptr;
func(ptr);
printf("%g\n",*(ptr+5)); // prints something other than 15
return 0;
}

This sort of makes sense, since I'm passing ptr as an argument. Is
there a way to pass ptr so that it behaves as expected? Or do I have
to do this?

Of course not. float receives a, of type float*, by value. Any
changes are not visible in main. You want:

void func(float* *a) {
if (*a = malloc(5 * sizeof(float))
*(*a + 4) = 15.0f;
/* ^-- *a only holds indices 0 thru 4 */
}

and in main you call "func(&ptr);". Better would be to have func
return the value of a, eliminating all the double **, and making
the call "ptr = func(ptr);".
 
H

henry

Functionarguments are always passed by value in C.

You can pass apointerto apointerinstead:

#include <stdio.h>
#include <stdlib.h>

void func(float **a)
{
*a = malloc(6 * sizeof **a);
if(*a)
*(*a+5) = 15.0f;
else {
fputs("No memory\n", stderr);
exit(EXIT_FAILURE);
}

}

int main(void)
{
float *ptr;
func(&ptr);
printf("%g\n", *(ptr+5));
free(ptr);
return 0;

}

(Note some other subtle difference from your code, too.)


Another example is strcpy(char *p, const char *s); why
it is not strcpy(char **p,const char *s)?
 
K

Keith Thompson

[...]
[attribution lost]
Function arguments are always passed by value in C.

You can pass a pointer to a pointer instead: [...]
void func(float **a)
{
*a = malloc(6 * sizeof **a);
if(*a)
*(*a+5) = 15.0f;
else {
fputs("No memory\n", stderr);
exit(EXIT_FAILURE);
}
[...]

Another example is strcpy(char *p, const char *s); why
it is not strcpy(char **p,const char *s)?

Because strcpy doesn't need to modify the pointer to the target
string; it only modifies the content of the string itself.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top