What you want to do is fine, but your code does not - main will never see the allocated memory. The myArray of myFunction parameter is initialized with the value passed in the function call, but after modifying it, it does not change the variable that is not associated with another name with the same name in main .
In your code snippet, the code line myFunction always returns 0 . If so, the most obvious way to fix your code is to return myArray instead (and not accept the parameter). Then the call to main will look like myArray = myFunction(); .
If myFunction is actually already using its return value, you can pass a pointer to double* and write the address in the referand of that pointer. This is what Ed Heal answers. The double ** parameter is often called "out-param" because it indicates the location that the function uses to store its output. In this case, the output is the address of the buffer.
An alternative would be to do something like this:
size_t myFunction(double *myArray, size_t buf_len) { int len=0; ... ... if (buf_len < len) { return len; } ... return len; }
Then the subscribers have the opportunity to allocate memory at their discretion. A typical call code might look like this:
size_t len = myFunction(NULL, 0); // warning -- watch the case where len == 0, if that is possible double *myArray = malloc(len * sizeof(*myArray)); if (!myArray) exit(1); myFunction(myArray, len); ... free(myArray);
What you got is that the caller can allocate memory from any convenient place. What you have lost is that the caller must write more code.
For an example of how to use this freedom, the caller can write:
#define SMALLSIZE 10; void one_of_several_jobs() { // doesn't usually require much space, occasionally does double smallbuf[SMALLSIZE]; double *buf = 0; size_t len = myFunction(smallbuf, SMALLSIZE); if (len > SMALLSIZE) { double *buf = malloc(len * sizeof(*buf)); if (!buf) { puts("this job is too big, skipping it and moving to the next one"); return; } } else { buf = smallbuf; } // use buf and len for something ... if (buf != smallbuf) free(buf); }
This is usually an unnecessary optimization to avoid malloc in the general case, when only a small buffer is required - this is just one example of why the caller might want to tell how the memory is allocated. A more urgent reason may be that your function is compiled into another dll from the caller function, possibly using a different compiler, and the two do not use compatible malloc/free implementations.