Skip to content

Instantly share code, notes, and snippets.

@PongsiriH
Created March 6, 2025 07:36
Generic stack implementation in C

Generic stack implementation in C

#include <malloc.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
typedef struct {
bool success;
union {
void *ok;
const char *err;
};
} StackResult;
typedef struct {
void *arr;
uint32_t top;
uint32_t capacity;
uint8_t element_size;
} Stack;
Stack *stack_init(uint8_t element_size) {
Stack *stack = malloc(sizeof(Stack));
if (stack == NULL) {
return NULL;
}
stack->capacity = 8;
stack->element_size = element_size;
stack->arr = malloc(stack->capacity * stack->element_size);
if (stack->arr == NULL) {
free(stack);
return NULL;
}
stack->top = 0;
return stack;
}
void stack_free(Stack *stack) {
if (stack != NULL) {
free(stack->arr);
free(stack);
}
}
bool stack_add(Stack *stack, void *value) {
if (stack->top >= stack->capacity) {
uint32_t new_capacity = stack->capacity * 2;
void *new_arr = realloc(stack->arr, new_capacity * stack->element_size);
if (new_arr == NULL) {
return false;
}
stack->capacity = new_capacity;
stack->arr = new_arr;
}
memcpy((char *)stack->arr + stack->top * stack->element_size, value,
stack->element_size);
stack->top++;
return true;
}
StackResult stack_pop(Stack *stack) {
if (stack->top == 0) {
return (StackResult){.success = false,
.err = "Failed to pop: Stack is empty."};
}
if (stack->top < stack->capacity / 4 && stack->capacity > 64) {
uint32_t new_capacity = stack->capacity / 2;
void *new_arr = realloc(stack->arr, new_capacity * stack->element_size);
if (new_arr != NULL) {
// It is ok if we fail to resize the array down.
stack->capacity = new_capacity;
stack->arr = new_arr;
}
}
stack->top--;
return (StackResult){.success = true,
.ok = (char *)stack->arr +
(stack->top * stack->element_size)};
}
void stack_print(Stack *stack, void (*print_function)(void *)) {
printf("[Stack] Capacity: %5d | Size: %5d | Element Size: %d\n",
stack->capacity, stack->top, stack->element_size);
printf("Stack elements: ");
for (int i = 0; i < stack->top; i++) {
char *data = ((char *)stack->arr + (i * stack->element_size));
print_function(data);
}
printf("\n");
}
void stack_metadata(Stack *stack) {
printf("[Stack] Capacity: %5d | Size: %5d | Element Size: %d\n",
stack->capacity, stack->top, stack->element_size);
}
void print_int(void *data) { printf("%d, ", *(int *)data); }
void print_double(void *data) { printf("%f, ", *(double *)data); }
void integer() {
Stack *s = stack_init(sizeof(int));
int a;
int b;
StackResult stack_result;
for (int i = 0; i < 1000; i++) {
stack_add(s, &i);
}
stack_metadata(s);
for (int i = 0; i < 800; i++) {
stack_pop(s);
}
stack_metadata(s);
stack_free(s);
}
void floating() {
Stack *s = stack_init(sizeof(double));
double value;
value = 52.2;
stack_add(s, &value);
value = 56.2;
stack_add(s, &value);
stack_print(s, print_double);
}
int main() {
integer();
printf("\n\n");
floating();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment