Dynamically-sized stack - follow-up 2
Use same case prefix for type "Stack" and functions "stack" --> "gStack" or whatever.
Use correct print specifier.  This implies that either OP does not have all warnings enabled or is using a weak compiler.  Suggest remedying that.

// printf("Size of stack is %d.\n", s1.stackSize);
printf("Size of stack is %u.\n", s1.stackSize);

Use consistent sign-ness

// int newStackSize;
unsigned newStackSize;

In push(), newStackSize test should be corrected or eliminated.

// if (temp == NULL || newStackSize == 0)

if (temp == NULL &amp;&amp; newStackSize &gt; 0)

// or if confident newStackSize will never be 0 here
if (temp == NULL)

Silently failing push() due to OOM is a concern.
pop() should do similar OOM protection as pop().  Even though it sounds silly that reducing memory usage should ever fail.
Consider putting all memory allocation into one helper function.  (BTW: destroy() did not free p-&gt;elementData.

static int stack_realloc(int **ptr, unsigned *oldsize, unsigned newsize) {
  if (newsize &gt; 0) {
    void *newptr = realloc(*ptr, newsize);
    if (newptr == NULL) return 1; // fail
    *ptr = newptr;
  }
  else {
    free(*ptr);
    *ptr = NULL;
  }
  *oldsize = newsize;
  return 0; // success;
}

// push()
unsigned newStackSize = p-&gt;stackSize + p-&gt;capacityIncrement;
if (stack_realloc(&amp;p-&gt;elementData, &amp;p-&gt;stackSize, newStackSize);

// pop()
// change from == to &gt;=
if(p-&gt;stackSize - p-&gt;elementCount &gt;= p-&gt;capacityIncrement / 2 + p-&gt;capacityIncrement) {
  unsigned newStackSize = p-&gt;stackSize - p-&gt;capacityIncrement;
  // No problem is realloc failed, just continue with current stack
  stack_realloc(&amp;p-&gt;elementData, &amp;p-&gt;stackSize, newStackSize);

// destroy() 
stack_realloc(&amp;p-&gt;elementData, &amp;p-&gt;stackSize, 0);
// Do not free `p`.
// free(p);