I think one is intending to implement a common container known a dynamic array for use in a stack (or similar structure.)
#include <stddef.h>
struct int_stack { int *data; size_t size, capacity; };
struct int_stack int_stack(void);
void int_stack_(struct int_stack *);
int *int_stack_new(struct int_stack *);
This is what I'd use as int_stack.h. Notice that it's logical size and it's capacity are not necessarily the same, but size <= capacity.
#include "int_stack.h"
#include <stdlib.h>
#include <errno.h>
/** Initialises `s` to idle. */
struct int_stack int_stack(void) {
    struct int_stack s;
    s.data = 0;
    s.capacity = s.size = 0;
    return s;
}
/** Destroys `s`; returns it idle. */
void int_stack_(struct int_stack *const s) {
    free(s->data);
    *s = int_stack();
}
/** Ensures `min_capacity` of `s`. Returns success, otherwise, `errno` will be
 set. */
static int int_stack_reserve(struct int_stack *const s, const size_t min) {
    size_t c0;
    int *data;
    const size_t max_size = (size_t)-1 / sizeof *s->data, min_size = 3;
    if(s->data) {
        if(min <= s->capacity) return 1;
        c0 = s->capacity < min_size ? min_size : s->capacity;
    } else { /* Idle. */
        if(!min) return 1;
        c0 = min_size;
    }
    if(min > max_size) return errno = ERANGE, 0;
    /* `c_n = a1.625^n`, approximation golden ratio `\phi ~ 1.618`. */
    while(c0 < min) {
        size_t c1 = c0 + (c0 >> 1) + (c0 >> 3);
        if(c0 > c1) { c0 = max_size; break; }
        c0 = c1;
    }
    if(!(data = realloc(s->data, sizeof *s->data * c0)))
        { if(!errno) errno = ERANGE; return 0; }
    s->data = data, s->capacity = c0;
    return 1;
}
/** Increases the capacity of `s` to at least `n` elements beyond the size.
 Returns the start of the buffered space at the back of the array or null and
 `errno`. */
static int *int_stack_buffer(struct int_stack *const s, const size_t n) {
    if(s->size > (size_t)-1 - n) { errno = ERANGE; return 0; } /* Unlikely. */
    return int_stack_reserve(s, s->size + n) && s->data ? s->data + s->size : 0;
}
/** Adds `n` elements to the back of `s` and returns a pointer to the elements.
 Null indicates an error and `errno` will be set. */
static int *int_stack_append(struct int_stack *const s, const size_t n) {
    int *buffer;
    if(!(buffer = int_stack_buffer(s, n))) return 0;
    return s->size += n, buffer;
}
/** Adds one new element of `s` and returns it as an uninitialized pointer or
 null and `errno`. */
int *int_stack_new(struct int_stack *const s) { return int_stack_append(s, 1); }
This is an example of what I'd use as the implementation int_stack.c. The function int_stack_reserve is where the realloc is called once the size reaches the capacity. A temporary data is assigned the realloc; this is checked for error, then assigned into s->data. Reserving a geometrically increasing capacity will avoid the cost of expanding each time. Thus, the array will have amortized cost of O(n) to insert n elements.
#include <stdio.h>
#include <stdlib.h>
#include "int_stack.h"
int main(void) {
    int status = EXIT_SUCCESS;
    int *e1, *e2;
    struct int_stack stack = int_stack();
    if(!(e1 = int_stack_new(&stack)) || !(e2 = int_stack_new(&stack))) {
        status = EXIT_FAILURE;
        perror("stack");
    } else {
        *e1 = 13;
        *e2 = 14;
        for(size_t i=0; i<stack.size; i++) {
            printf("%d  ", stack.data[i]);
        }
        fputc('\n', stdout);
    }
    int_stack_(&stack);
    return status;
}
Instead of a fixed-size, we now have unlimited size, but one has to check for out-of-memory condition.
     
    
array2is a local variable.reallocreturn a value? what's the purpose of it? could it just have returnedvoid?"