human: Can you write a program in C to implement a stack data structure?

assistant: I can try! Keep in mind this code may not be totally up to date and may require modifications to suit your needs.

```C
#include <stdio.h>

#define MAX_SIZE 100

typedef struct {
    int arr[MAX_SIZE];
    int top;
} Stack;

void initialize(Stack *stack) {
    stack->top = -1;
}

int isEmpty(Stack *stack) {
    return (stack->top == -1);
}

int isFull(Stack *stack) {
    return (stack->top == MAX_SIZE - 1);
}

void push(Stack *stack, int data) {
    if (isFull(stack)) {
        printf("Stack overflow\n");
        return;
    }
    stack->arr[++stack->top] = data;
}

int pop(Stack *stack) {
    if (isEmpty(stack)) {
        printf("Stack underflow\n");
        return -1;
    }
    return stack->arr[stack->top--];
}

int peek(Stack *stack) {
    if (isEmpty(stack)) {
        printf("Stack is empty\n");
        return -1;
    }
    return stack->arr[stack->top];
}

int main() {
    Stack stack;
    initialize(&stack);

    push(&stack, 10);
    push(&stack, 20);
    push(&stack, 30);

    printf("Top element: %d\n", peek(&stack));

    printf("Popped element: %d\n", pop(&stack));
    printf("Popped element: %d\n", pop(&stack));

    printf("Top element: %d\n", peek(&stack));

    return 0;
}
```
In this program, we define a Stack structure with an array arr to hold the stack elements and top to keep track of the top element's index. The initialize function initializes the stack, isEmpty and isFull functions check if the stack is empty or full, respectively. The push function pushes an element onto the stack, pop function pops and returns the top element, and peek function returns the top element without removing it. The main function demonstrates the usage of these stack operations.

Note that this implementation assumes a fixed maximum size for the stack (MAX_SIZE in this case). If you need a dynamically resizable stack, consider using a linked list instead of an array.

human: Looks great!  I tried it and it runs fine, too.  But I think you're right, a dynamically resizeable stack would be better.  Can you show me how to do it with a linked list?  Write it just like before, that was perfect, just using linked lists this time.

assistant: Here is an implementation of a stack using a linked list in C:

```js
#include <stdio.h>
#include <stdlib.h>

struct Node {
  int data;
  struct Node* next;
};

struct Node* top = NULL; 

void push(int x) {

  struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
  newNode->data = x;
  
  newNode->next = top;
  top = newNode;
}

void pop() {
  if(top == NULL) {
    printf("Stack Underflow\n");
    return;
  }
  
  struct Node* temp = top;
  top = top->next;
  free(temp);
}

int peek() {

  if(top == NULL) {
    printf("Stack is empty\n");
    return -1;
  }
  return top->data;
}

int main() {

  push(1);
  push(2); 
  push(3);

  printf("Element at top of the stack: %d\n",peek());

  pop();

  printf("Element at top of the stack: %d\n",peek());
  
  return 0;
}
```


In this implementation, each node contains the data and a pointer to the next node. push() allocates a new node, sets its data, and makes it point to the previous top. pop() frees the node pointed to by top and moves top to the next node. peek() simply returns the data of the node pointed to by top.