Exemplo da ficha 6 de PI :

main.c

/* Main function of the C program. */

#include <stdio.h>
#include "Stack.h"

int main() {
  int i ; 
  struct staticStack s1;
  SStack S1 = &s1;
  struct dinStack d1;
  DStack D1 = &d1;
  
  printf ("Testing Stacks .... \\n");
  SinitStack (S1);
  DinitStack (D1);
  for (i=0; i<15; i++) {
    if (Spush (S1,i) != 0) printf ("ERROR pushing %d\\n", i);
    if (Dpush (D1,i) != 0) printf ("ERROR pushing %d\\n", i);
  }
  
  // funcao que faz pop de todos os elementos e vai imprimindo cada elemento
  while (!SisEmpty(S1)) {
      Spop(S1, &i);
      printf("%d ",i);
  }
  printf("\\n");
  
  //ShowSStack (S1);
  ShowDStack (D1);
  
  return 0;
}

Stack.c

#include <stdio.h>
#include <stdlib.h>
#include "Stack.h"

// Static stacks 

void SinitStack (SStack s){
	s->sp = 0;
}

int  SisEmpty (SStack s){
    int r;
    if (s->sp == 0) r = 1;
    else r = 0;
    return r; // se for falso retorna 0, se for verdadeiro retorna alguma coisa diferente de 0
}

int  Spush (SStack s, int x){
	// primeiro detetar se há capacidade no array
	if (s->sp == Max) return 1;
	// Se houver espaço, inserir o valor na stack
	s->values[s->sp] = x;
	s->sp++;
	
	return 0;
}

int  Spop (SStack s, int *x) {
	int r=0;
	if (s->sp == 0) r = 1;
	else {
	    s->sp--;
	    *x = s->values[s->sp];
	}
	return r;
}

int  Stop (SStack s, int *x) {
	int r=0;
	if (s->sp == 0) r = 1;
	else {
	    *x = s->values[s->sp-1];
	}
	return r;
}

void ShowSStack (SStack s){
    int i;
    printf ("%d Items: ", s->sp);
    for (i=s->sp-1; i>=0; i--) 
        printf ("%d ", s->values[i]);
    putchar ('\\n');
}

// Stacks with dynamic arrays

int dupStack (DStack s) {
	int r = 0, i;
	int *t = malloc (2*s->size*sizeof(int)); // Neste caso estamos a reservar o dobro do espaco que tinhamos antes

	if (t == NULL) r = 1; // verificar o resultado do malloc para ter certeza que a alocacao de memoria nao falha
	else {
		for (i=0; i<s->size; i++) // copiar os elementos
			t[i] = s->values[i]; // para a nova memoria alocada
		free (s->values); // libertar a memoria antiga
		s->values = t; // guardo o t em values, ou seja, values fica a apontar para a nova zona de memoria
		s->size*=2; // muda o valor do tamanho total da struct
	}
	return r;
	
	/*
	Esta funcao copia os elementos na struct inicial para a outra que foi criada com um espaco maior
	*/
}

// Versao com o realloc
int dupStack (DStack s) {
	int r = 0;
	int *t = realloc (s->values, 2*s->size*sizeof(int)); // Neste caso estamos a reservar o dobro do espaco que tinhamos antes

	if (t == NULL) r = 1; // verificar o resultado do malloc para ter certeza que a alocacao de memoria nao falha
	else {
		s->values = t; // guardo o t em values, ou seja, values fica a apontar para a nova zona de memoria
		s->size*=2; // muda o valor do tamanho total da struct
	}
	return r;
}

void DinitStack (DStack s) {
		s->sp = 0;
		s->size = 1; // memoria a ser alocada inicialmente (é aconselhado alocar um pedaco maior ja no começo)
		s->values = malloc (s->size * sizeof(int)); // alocar memoria
}

int  DisEmpty (DStack s) {
    int r;
    if (s->sp == 0) r = 1;
    else r = 0;
    return r; // se for falso retorna 0, se for verdadeiro retorna alguma coisa diferente de 0
}

int  Dpush (DStack s, int x){
	int r=0;
	if (s->sp == s->size) { // se nao tiver capacidade aloca mais memoria
	    r = dupStack(s);
	}
	if (r == 0) { // ou seja, se tiver capacidade
	    s->values[s->sp] = x;
	    s->sp++;
	}
	return r;
}

int  Dpop (DStack s, int *x){
	int r=0;
	
	return r;
}

int  Dtop (DStack s, int *x){
	int r=0;
	
	return r;
}

void ShowDStack (DStack s){
    int i;
    printf ("%d Items: ", s->sp);
    for (i=s->sp-1; i>=0; i--) 
        printf ("%d ", s->values[i]);
    putchar ('\\n');
}

Stack.h

#define Max 10

struct staticStack {
	int sp; // tamanho da stack - sp = stack pointer
	int values [Max];
};
typedef struct staticStack *SStack;

struct dinStack {
	int size; // tamanho total / capacidade de memoória da struct
	int sp; // tamanho da stack em cada momento - sp = stack pointer
	int *values;
};
typedef struct dinStack *DStack;

void SinitStack (SStack s);
int  SisEmpty (SStack s);
int  Spush (SStack s, int x);
int  Spop (SStack s, int *x);
int  Stop (SStack s, int *x);
void ShowSStack (SStack s);

void DinitStack (DStack s);
int  DisEmpty (DStack s);
int  Dpush (DStack s, int x);
int  Dpop (DStack s, int *x);
int  Dtop (DStack s, int *x);
void ShowDStack (DStack s);

Link para memória e alocação de memória