You have to pass the address of the pointer ("&myArray") to the function. So, the argument is of type "double**" (the address to some address).
If you just passed the pointer ("myArray"), i.e. using your first function from the list, then the function "overwrites" its value, and the caller basically "lost" the pointer; also this would be a memory leak.
It doesnt make sense to pass the value of the pointer ("*myArray"), i.e. using your last function from the list, because that doesnt achieve anything. I dont know how to explain this one, hopefully its obvious! Its just passing a "double", like "createArray( 1.0, size)", which doesnt make sense.
I never use the syntax for the 3rd one, and I dont even think its correct.
This leaves the second function, "double**". As mentioned above, the caller calls this function by passing the address of the pointer, i.e.:
The function then doesnt modify this argument's value (if it did, the caller would "loose" it, as above), rather it modifies the value at this value's address (i.e. *myArray). So createArray uses malloc to create the dynamic array, and assigns it to the value pointed to by the pointer, i.e.:
Now the caller still "knows" where this new array was created, because the address of "myArray" wasnt changed, only its value. And its value is now the (first index of) the array created by createArray.
void createArray(double** array, int size)
*array = malloc( sizeof(double) * size); // go to the value of "array" (i.e. the address of myArray), and save the address of this new array at its value (i.e. myArray = this new array)
Hope its clear... try and draw out a picture of whats going on, one for each of your 4 cases, to see whats happening, and cancel out the ones that dont work. Let us know if you have questions.
EDIT: The reason you have to do it the above way, is because your changing the pointers value, i.e. giving it a different piece of memory... which means you have to pass its address, so you still know where it is. If you werent changing its value, such as printing the values of the array, it would be straightforward and you could just pass the pointer, i.e.
A similar thing would be done if you were manipulating its contents, such as reversing the values in the list. Doing something like "array = array" is quite different from doing "array = // new address".
void printArray(double * array, int size)
// iterate over and print
double * array;
// create and fill up array