I've been trying to wrap my isignificant brain around this thing called pointers. So I challenged myself to the following code, which is a push function that "grows" an array dynamically.

I ran this code through valgrind memcheck, and no errors occured

There might be more than one thing wrong with this code, don't hold back!

But my main question is: why do I have to encase the dereferenced double pointer 'p' in parenthesis after realloc in the push function? (i.e: line14)

the code:

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

/* This example has been kept simple and without error handling */
void push(int **p, int i, int val)
{
    /* allocate memory */
    if(*p == NULL){
        *p = malloc(sizeof(int));
        *p[i] = val;
    }else{
        /* reallocate memory to grow array */
        *p = realloc(*p, ((i + 1) * sizeof(int)));
        (*p)[i] = val;
    }
}

int main(void)
{
    int *p = NULL;

    /* Pushing three elements to array, using index and value */
    push(&p, 0, 123);
    push(&p, 1, 321);
    push(&p, 2, 777);


    printf("value index 0: %d\n", p[0]);
    printf("value index 1: %d\n", p[1]);
    printf("value index 2: %d\n", p[2]);


    free(p);


    return 0;
}