Q:

Why don't I have to give the function the address of the array

Hi I'm new to C and learning about pointers. I'm writing a simple recursive function to test it where it takes parameters int *a and int size. In my main method, I send print_array the address of the first character of my array using the & beforehand.
This doesn't seem to work, I get given an "incompatible pointer types" error at compilation. I understand that I can remove the & and the program works fine. I have a question:
Why can't I pass in the memory address of my_array from main with a &? Shouldn't I be able to just give the function the memory address of first element of array and it can deal with the rest? 
Thanks, hope this question wasn't too noob.
 #include <stdio.h>
 #include <stdlib.h>

void print_array(int *a, int size){
    if (size>0){
            printf("%d\n", a[0]);
            print_array(a+1, size-1);
    }
}

int main(void){
    int my_array[20];
    int i;

    for (i=0; i < 20; i++){
            my_array[i] = rand() % 20;
    }

    /*the contents of the array*/
    printf("The contents of the array\n");
    for (i=0; i < 20; i++){
            printf("%d\n", my_array[i]);
    }

    printf("The recursive method print\n");

    print_array(&my_array, 20);

    return EXIT_SUCCESS;

}

A:

Yes, you can give the function the address of the first element, and let it deal with the rest. You could do that as either:
print_array(my_array, 20);

...or:
print_array(&my_array[0], 20);

Unfortunately, while &my_array is legal code, it produces a pointer to the entire array, rather than a pointer to the first element of the array. Those have the same address, but different types, which is what's causing the error.
The type of a pointer determines (among other things) how arithmetic on that pointer will work. In your case, print_array prints the first int in the array, then adds one to the pointer. Since it's a pointer to int, that addition actually adds the size of an int to the address in the pointer.
If you used a pointer to the entire array, then adding one would instead add the size of the entire array to the address. For example, let's assume 4-byte ints and that my_array has a base address of 1000. In this case, my_array+1 will yield 1004, so it holds the address of the second int in the array (just as you undoubtedly wanted). By contrast, &my_array will take the address of the entire array, with the type "pointer to array of 20 ints". When you add one to it, that will add 1 * the size of the pointed-to type to the address, so you'll get 1080 (i.e., the entire array is 20 * 4 = 80 bytes). This is obviously not what you wanted--instead of x+1 pointing to the second item in the array, it now points past the end of the array, and attempting to dereference the pointer will give undefined behavior.
So, just switch to one of the forms above (my_array or &my_array[0]). As a more general point, realize that the name of an array evaluates as a pointer to the first element of the array under most circumstances--the notable exceptions being when you use the name of the array as a the operand of either the sizeof operator or the address-of operator (as you did here). In these two cases, the name of the array still refers to the entire array instead of a pointer to the first element.

