c
examples
examples.c🔧c
/**
* Dynamic Arrays in C - Examples
*
* This file contains comprehensive examples demonstrating
* dynamic array creation, manipulation, and various implementations.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
/* ============================================================
* Example 1: Basic Dynamic Array Operations
* ============================================================ */
void example_basic_dynamic_array(void) {
printf("=== Example 1: Basic Dynamic Array Operations ===\n\n");
/* Declare a pointer for our dynamic array */
int *arr = NULL;
size_t size = 0;
size_t capacity = 4;
/* Initial allocation */
arr = malloc(capacity * sizeof(int));
if (!arr) {
fprintf(stderr, "Initial allocation failed!\n");
return;
}
printf("Initial capacity: %zu\n", capacity);
/* Add elements with automatic growing */
for (int i = 0; i < 10; i++) {
/* Check if we need to grow */
if (size >= capacity) {
capacity *= 2;
printf("Growing array to capacity: %zu\n", capacity);
int *temp = realloc(arr, capacity * sizeof(int));
if (!temp) {
fprintf(stderr, "Reallocation failed!\n");
free(arr);
return;
}
arr = temp;
}
arr[size++] = i * 10;
}
/* Print the array */
printf("\nArray contents (size=%zu, capacity=%zu): ", size, capacity);
for (size_t i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n\n");
free(arr);
}
/* ============================================================
* Example 2: Array of Pointers for 2D Dynamic Array
* ============================================================ */
void example_2d_array_pointers(void) {
printf("=== Example 2: 2D Array Using Array of Pointers ===\n\n");
size_t rows = 3;
size_t cols = 4;
/* Allocate array of row pointers */
int **matrix = malloc(rows * sizeof(int *));
if (!matrix) {
fprintf(stderr, "Failed to allocate row pointers!\n");
return;
}
/* Allocate each row */
for (size_t i = 0; i < rows; i++) {
matrix[i] = malloc(cols * sizeof(int));
if (!matrix[i]) {
fprintf(stderr, "Failed to allocate row %zu!\n", i);
/* Cleanup already allocated rows */
while (i > 0) free(matrix[--i]);
free(matrix);
return;
}
}
/* Initialize with values */
int value = 1;
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
matrix[i][j] = value++;
}
}
/* Print the matrix */
printf("Matrix (%zux%zu):\n", rows, cols);
for (size_t i = 0; i < rows; i++) {
printf(" [ ");
for (size_t j = 0; j < cols; j++) {
printf("%3d ", matrix[i][j]);
}
printf("]\n");
}
printf("\n");
/* Free the matrix */
for (size_t i = 0; i < rows; i++) {
free(matrix[i]);
}
free(matrix);
}
/* ============================================================
* Example 3: Contiguous 2D Array (Better Cache Performance)
* ============================================================ */
typedef struct {
int *data;
size_t rows;
size_t cols;
} ContiguousMatrix;
ContiguousMatrix *cm_create(size_t rows, size_t cols) {
ContiguousMatrix *m = malloc(sizeof(ContiguousMatrix));
if (!m) return NULL;
m->data = calloc(rows * cols, sizeof(int));
if (!m->data) {
free(m);
return NULL;
}
m->rows = rows;
m->cols = cols;
return m;
}
void cm_destroy(ContiguousMatrix *m) {
if (m) {
free(m->data);
free(m);
}
}
int cm_get(ContiguousMatrix *m, size_t r, size_t c) {
return m->data[r * m->cols + c];
}
void cm_set(ContiguousMatrix *m, size_t r, size_t c, int val) {
m->data[r * m->cols + c] = val;
}
void example_contiguous_2d_array(void) {
printf("=== Example 3: Contiguous 2D Array ===\n\n");
ContiguousMatrix *m = cm_create(3, 4);
if (!m) {
fprintf(stderr, "Failed to create matrix!\n");
return;
}
/* Initialize */
int value = 1;
for (size_t i = 0; i < m->rows; i++) {
for (size_t j = 0; j < m->cols; j++) {
cm_set(m, i, j, value++);
}
}
/* Print */
printf("Contiguous Matrix:\n");
for (size_t i = 0; i < m->rows; i++) {
printf(" [ ");
for (size_t j = 0; j < m->cols; j++) {
printf("%3d ", cm_get(m, i, j));
}
printf("]\n");
}
/* Show memory layout */
printf("\nMemory layout (all data contiguous):\n ");
for (size_t i = 0; i < m->rows * m->cols; i++) {
printf("%d ", m->data[i]);
}
printf("\n\n");
cm_destroy(m);
}
/* ============================================================
* Example 4: Generic Dynamic Array (Integer Version)
* ============================================================ */
#define INITIAL_CAPACITY 4
#define GROWTH_FACTOR 2
typedef struct {
int *data;
size_t size;
size_t capacity;
} IntVector;
IntVector *ivec_create(void) {
IntVector *v = malloc(sizeof(IntVector));
if (!v) return NULL;
v->data = malloc(INITIAL_CAPACITY * sizeof(int));
if (!v->data) {
free(v);
return NULL;
}
v->size = 0;
v->capacity = INITIAL_CAPACITY;
return v;
}
void ivec_destroy(IntVector *v) {
if (v) {
free(v->data);
free(v);
}
}
int ivec_push(IntVector *v, int value) {
if (v->size >= v->capacity) {
size_t new_cap = v->capacity * GROWTH_FACTOR;
int *temp = realloc(v->data, new_cap * sizeof(int));
if (!temp) return -1;
v->data = temp;
v->capacity = new_cap;
}
v->data[v->size++] = value;
return 0;
}
int ivec_pop(IntVector *v) {
if (v->size == 0) return 0;
return v->data[--v->size];
}
int ivec_get(IntVector *v, size_t index) {
if (index >= v->size) return 0;
return v->data[index];
}
void ivec_set(IntVector *v, size_t index, int value) {
if (index < v->size) {
v->data[index] = value;
}
}
void ivec_print(IntVector *v) {
printf("IntVector [size=%zu, cap=%zu]: ", v->size, v->capacity);
for (size_t i = 0; i < v->size; i++) {
printf("%d ", v->data[i]);
}
printf("\n");
}
void example_int_vector(void) {
printf("=== Example 4: Integer Vector Implementation ===\n\n");
IntVector *v = ivec_create();
if (!v) {
fprintf(stderr, "Failed to create vector!\n");
return;
}
/* Push elements */
printf("Pushing elements 0-9:\n");
for (int i = 0; i < 10; i++) {
ivec_push(v, i);
printf(" After pushing %d: ", i);
ivec_print(v);
}
/* Pop elements */
printf("\nPopping 3 elements:\n");
for (int i = 0; i < 3; i++) {
int val = ivec_pop(v);
printf(" Popped: %d, ", val);
ivec_print(v);
}
/* Modify element */
printf("\nSetting index 2 to 100:\n");
ivec_set(v, 2, 100);
ivec_print(v);
printf("\n");
ivec_destroy(v);
}
/* ============================================================
* Example 5: Single Allocation 2D Array (Array of Pointers + Data)
* ============================================================ */
int **create_unified_2d(size_t rows, size_t cols) {
/* Single allocation for pointers + data */
int **arr = malloc(rows * sizeof(int *) + rows * cols * sizeof(int));
if (!arr) return NULL;
/* Data starts after the pointer array */
int *data = (int *)(arr + rows);
/* Set up row pointers */
for (size_t i = 0; i < rows; i++) {
arr[i] = data + i * cols;
}
return arr;
}
void destroy_unified_2d(int **arr) {
free(arr); /* Single free */
}
void example_unified_2d_array(void) {
printf("=== Example 5: Unified 2D Array (Single Allocation) ===\n\n");
size_t rows = 3;
size_t cols = 5;
int **arr = create_unified_2d(rows, cols);
if (!arr) {
fprintf(stderr, "Failed to create array!\n");
return;
}
/* Initialize */
int val = 1;
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
arr[i][j] = val++;
}
}
/* Print using standard 2D syntax */
printf("Array contents:\n");
for (size_t i = 0; i < rows; i++) {
printf(" Row %zu: ", i);
for (size_t j = 0; j < cols; j++) {
printf("%3d ", arr[i][j]);
}
printf("\n");
}
/* Show that pointers are contiguous */
printf("\nRow pointers (addresses):\n");
for (size_t i = 0; i < rows; i++) {
printf(" arr[%zu] = %p\n", i, (void *)arr[i]);
}
printf("\n");
destroy_unified_2d(arr);
}
/* ============================================================
* Example 6: Jagged Array (Rows of Different Sizes)
* ============================================================ */
typedef struct {
int *data;
size_t length;
} Row;
typedef struct {
Row *rows;
size_t num_rows;
} JaggedArray;
JaggedArray *jagged_create(size_t num_rows) {
JaggedArray *j = malloc(sizeof(JaggedArray));
if (!j) return NULL;
j->rows = calloc(num_rows, sizeof(Row));
if (!j->rows) {
free(j);
return NULL;
}
j->num_rows = num_rows;
return j;
}
int jagged_set_row(JaggedArray *j, size_t row_idx, size_t length) {
if (row_idx >= j->num_rows) return -1;
/* Free existing row if present */
free(j->rows[row_idx].data);
j->rows[row_idx].data = calloc(length, sizeof(int));
if (!j->rows[row_idx].data && length > 0) return -1;
j->rows[row_idx].length = length;
return 0;
}
void jagged_destroy(JaggedArray *j) {
if (j) {
for (size_t i = 0; i < j->num_rows; i++) {
free(j->rows[i].data);
}
free(j->rows);
free(j);
}
}
void example_jagged_array(void) {
printf("=== Example 6: Jagged Array (Variable Row Lengths) ===\n\n");
JaggedArray *j = jagged_create(5);
if (!j) {
fprintf(stderr, "Failed to create jagged array!\n");
return;
}
/* Create rows of different lengths (like Pascal's triangle shape) */
size_t lengths[] = {1, 2, 3, 4, 5};
for (size_t i = 0; i < 5; i++) {
jagged_set_row(j, i, lengths[i]);
/* Fill row with values */
for (size_t k = 0; k < lengths[i]; k++) {
j->rows[i].data[k] = (int)(i * 10 + k);
}
}
/* Print jagged array */
printf("Jagged Array:\n");
for (size_t i = 0; i < j->num_rows; i++) {
printf(" Row %zu (len=%zu): [ ", i, j->rows[i].length);
for (size_t k = 0; k < j->rows[i].length; k++) {
printf("%2d ", j->rows[i].data[k]);
}
printf("]\n");
}
printf("\n");
jagged_destroy(j);
}
/* ============================================================
* Example 7: Dynamic Array with Insert and Remove
* ============================================================ */
typedef struct {
int *data;
size_t size;
size_t capacity;
} DynArray;
DynArray *da_create(void) {
DynArray *arr = malloc(sizeof(DynArray));
if (!arr) return NULL;
arr->data = malloc(8 * sizeof(int));
if (!arr->data) {
free(arr);
return NULL;
}
arr->size = 0;
arr->capacity = 8;
return arr;
}
void da_destroy(DynArray *arr) {
if (arr) {
free(arr->data);
free(arr);
}
}
int da_ensure_capacity(DynArray *arr, size_t min_cap) {
if (min_cap <= arr->capacity) return 0;
size_t new_cap = arr->capacity;
while (new_cap < min_cap) new_cap *= 2;
int *temp = realloc(arr->data, new_cap * sizeof(int));
if (!temp) return -1;
arr->data = temp;
arr->capacity = new_cap;
return 0;
}
int da_insert(DynArray *arr, size_t index, int value) {
if (index > arr->size) return -1;
if (da_ensure_capacity(arr, arr->size + 1) != 0) return -1;
/* Shift elements right */
memmove(&arr->data[index + 1], &arr->data[index],
(arr->size - index) * sizeof(int));
arr->data[index] = value;
arr->size++;
return 0;
}
int da_remove(DynArray *arr, size_t index) {
if (index >= arr->size) return -1;
int removed = arr->data[index];
/* Shift elements left */
memmove(&arr->data[index], &arr->data[index + 1],
(arr->size - index - 1) * sizeof(int));
arr->size--;
return removed;
}
void da_push(DynArray *arr, int value) {
da_insert(arr, arr->size, value);
}
void da_print(DynArray *arr) {
printf("[");
for (size_t i = 0; i < arr->size; i++) {
printf("%d", arr->data[i]);
if (i < arr->size - 1) printf(", ");
}
printf("] (size=%zu, cap=%zu)\n", arr->size, arr->capacity);
}
void example_insert_remove(void) {
printf("=== Example 7: Dynamic Array with Insert/Remove ===\n\n");
DynArray *arr = da_create();
if (!arr) return;
/* Build initial array */
for (int i = 0; i < 5; i++) {
da_push(arr, i * 10);
}
printf("Initial: ");
da_print(arr);
/* Insert at beginning */
da_insert(arr, 0, 99);
printf("Insert 99 at start: ");
da_print(arr);
/* Insert in middle */
da_insert(arr, 3, 55);
printf("Insert 55 at index 3: ");
da_print(arr);
/* Insert at end */
da_insert(arr, arr->size, 77);
printf("Insert 77 at end: ");
da_print(arr);
/* Remove from middle */
int removed = da_remove(arr, 3);
printf("Remove from index 3 (got %d): ", removed);
da_print(arr);
/* Remove from start */
removed = da_remove(arr, 0);
printf("Remove from start (got %d): ", removed);
da_print(arr);
printf("\n");
da_destroy(arr);
}
/* ============================================================
* Example 8: String Array (Dynamic Array of Strings)
* ============================================================ */
typedef struct {
char **strings;
size_t size;
size_t capacity;
} StringArray;
StringArray *sa_create(void) {
StringArray *sa = malloc(sizeof(StringArray));
if (!sa) return NULL;
sa->strings = malloc(4 * sizeof(char *));
if (!sa->strings) {
free(sa);
return NULL;
}
sa->size = 0;
sa->capacity = 4;
return sa;
}
void sa_destroy(StringArray *sa) {
if (sa) {
for (size_t i = 0; i < sa->size; i++) {
free(sa->strings[i]);
}
free(sa->strings);
free(sa);
}
}
int sa_push(StringArray *sa, const char *str) {
if (sa->size >= sa->capacity) {
size_t new_cap = sa->capacity * 2;
char **temp = realloc(sa->strings, new_cap * sizeof(char *));
if (!temp) return -1;
sa->strings = temp;
sa->capacity = new_cap;
}
sa->strings[sa->size] = strdup(str);
if (!sa->strings[sa->size]) return -1;
sa->size++;
return 0;
}
const char *sa_get(StringArray *sa, size_t index) {
if (index >= sa->size) return NULL;
return sa->strings[index];
}
void sa_print(StringArray *sa) {
printf("StringArray [size=%zu]:\n", sa->size);
for (size_t i = 0; i < sa->size; i++) {
printf(" [%zu]: \"%s\"\n", i, sa->strings[i]);
}
}
void example_string_array(void) {
printf("=== Example 8: Dynamic String Array ===\n\n");
StringArray *sa = sa_create();
if (!sa) return;
/* Add strings */
sa_push(sa, "Hello");
sa_push(sa, "World");
sa_push(sa, "Dynamic");
sa_push(sa, "Arrays");
sa_push(sa, "in C");
sa_print(sa);
/* Access specific string */
printf("\nElement at index 2: \"%s\"\n\n", sa_get(sa, 2));
sa_destroy(sa);
}
/* ============================================================
* Example 9: Growth Strategy Comparison
* ============================================================ */
void example_growth_strategies(void) {
printf("=== Example 9: Growth Strategy Comparison ===\n\n");
/* Simulate different growth strategies */
printf("Inserting 1000 elements with different strategies:\n\n");
/* Strategy 1: Add 10 each time */
{
size_t capacity = 10;
size_t size = 0;
int reallocations = 0;
for (int i = 0; i < 1000; i++) {
if (size >= capacity) {
capacity += 10; /* Linear growth */
reallocations++;
}
size++;
}
printf("Linear (+10): %d reallocations, final capacity: %zu\n",
reallocations, capacity);
}
/* Strategy 2: Double each time */
{
size_t capacity = 4;
size_t size = 0;
int reallocations = 0;
for (int i = 0; i < 1000; i++) {
if (size >= capacity) {
capacity *= 2; /* Doubling */
reallocations++;
}
size++;
}
printf("Doubling (2x): %d reallocations, final capacity: %zu\n",
reallocations, capacity);
}
/* Strategy 3: Multiply by 1.5 */
{
size_t capacity = 4;
size_t size = 0;
int reallocations = 0;
for (int i = 0; i < 1000; i++) {
if (size >= capacity) {
capacity = capacity + capacity / 2; /* 1.5x growth */
reallocations++;
}
size++;
}
printf("1.5x growth: %d reallocations, final capacity: %zu\n",
reallocations, capacity);
}
printf("\n");
}
/* ============================================================
* Example 10: Memory-Efficient Bit Array
* ============================================================ */
typedef struct {
unsigned char *data;
size_t num_bits;
} BitArray;
BitArray *bitarray_create(size_t num_bits) {
BitArray *ba = malloc(sizeof(BitArray));
if (!ba) return NULL;
size_t num_bytes = (num_bits + 7) / 8;
ba->data = calloc(num_bytes, 1);
if (!ba->data) {
free(ba);
return NULL;
}
ba->num_bits = num_bits;
return ba;
}
void bitarray_destroy(BitArray *ba) {
if (ba) {
free(ba->data);
free(ba);
}
}
void bitarray_set(BitArray *ba, size_t index) {
if (index >= ba->num_bits) return;
ba->data[index / 8] |= (1 << (index % 8));
}
void bitarray_clear(BitArray *ba, size_t index) {
if (index >= ba->num_bits) return;
ba->data[index / 8] &= ~(1 << (index % 8));
}
int bitarray_get(BitArray *ba, size_t index) {
if (index >= ba->num_bits) return 0;
return (ba->data[index / 8] >> (index % 8)) & 1;
}
void bitarray_print(BitArray *ba) {
printf("BitArray [%zu bits]: ", ba->num_bits);
for (size_t i = 0; i < ba->num_bits; i++) {
printf("%d", bitarray_get(ba, i));
if ((i + 1) % 8 == 0 && i + 1 < ba->num_bits) printf(" ");
}
printf("\n");
}
void example_bit_array(void) {
printf("=== Example 10: Memory-Efficient Bit Array ===\n\n");
BitArray *ba = bitarray_create(16);
if (!ba) return;
printf("Initial (all zeros):\n");
bitarray_print(ba);
/* Set some bits */
bitarray_set(ba, 0);
bitarray_set(ba, 3);
bitarray_set(ba, 7);
bitarray_set(ba, 8);
bitarray_set(ba, 15);
printf("\nAfter setting bits 0, 3, 7, 8, 15:\n");
bitarray_print(ba);
/* Clear a bit */
bitarray_clear(ba, 3);
printf("\nAfter clearing bit 3:\n");
bitarray_print(ba);
/* Memory comparison */
printf("\nMemory usage comparison for 1000 flags:\n");
printf(" int array: %zu bytes\n", 1000 * sizeof(int));
printf(" bit array: %zu bytes\n", (1000 + 7) / 8);
printf("\n");
bitarray_destroy(ba);
}
/* ============================================================
* Example 11: Circular Buffer
* ============================================================ */
typedef struct {
int *data;
size_t capacity;
size_t head;
size_t tail;
size_t size;
} CircularBuffer;
CircularBuffer *cb_create(size_t capacity) {
CircularBuffer *cb = malloc(sizeof(CircularBuffer));
if (!cb) return NULL;
cb->data = malloc(capacity * sizeof(int));
if (!cb->data) {
free(cb);
return NULL;
}
cb->capacity = capacity;
cb->head = 0;
cb->tail = 0;
cb->size = 0;
return cb;
}
void cb_destroy(CircularBuffer *cb) {
if (cb) {
free(cb->data);
free(cb);
}
}
int cb_push(CircularBuffer *cb, int value) {
if (cb->size >= cb->capacity) return -1; /* Full */
cb->data[cb->tail] = value;
cb->tail = (cb->tail + 1) % cb->capacity;
cb->size++;
return 0;
}
int cb_pop(CircularBuffer *cb, int *out) {
if (cb->size == 0) return -1; /* Empty */
*out = cb->data[cb->head];
cb->head = (cb->head + 1) % cb->capacity;
cb->size--;
return 0;
}
void cb_print(CircularBuffer *cb) {
printf("CircularBuffer [size=%zu, cap=%zu]: ", cb->size, cb->capacity);
size_t i = cb->head;
for (size_t count = 0; count < cb->size; count++) {
printf("%d ", cb->data[i]);
i = (i + 1) % cb->capacity;
}
printf("\n");
}
void example_circular_buffer(void) {
printf("=== Example 11: Circular Buffer ===\n\n");
CircularBuffer *cb = cb_create(5);
if (!cb) return;
/* Fill the buffer */
printf("Pushing 1, 2, 3, 4, 5:\n");
for (int i = 1; i <= 5; i++) {
cb_push(cb, i);
}
cb_print(cb);
/* Pop some */
int val;
cb_pop(cb, &val);
printf("\nPopped %d:\n", val);
cb_print(cb);
cb_pop(cb, &val);
printf("\nPopped %d:\n", val);
cb_print(cb);
/* Push more */
printf("\nPushing 10, 20:\n");
cb_push(cb, 10);
cb_push(cb, 20);
cb_print(cb);
/* Show circular nature */
printf("\nCircular wrap-around demonstrated!\n");
printf("(Data wraps around the fixed-size buffer)\n\n");
cb_destroy(cb);
}
/* ============================================================
* Example 12: Stack Implementation Using Dynamic Array
* ============================================================ */
typedef struct {
int *data;
size_t size;
size_t capacity;
} Stack;
Stack *stack_create(void) {
Stack *s = malloc(sizeof(Stack));
if (!s) return NULL;
s->data = malloc(8 * sizeof(int));
if (!s->data) {
free(s);
return NULL;
}
s->size = 0;
s->capacity = 8;
return s;
}
void stack_destroy(Stack *s) {
if (s) {
free(s->data);
free(s);
}
}
int stack_push(Stack *s, int value) {
if (s->size >= s->capacity) {
size_t new_cap = s->capacity * 2;
int *temp = realloc(s->data, new_cap * sizeof(int));
if (!temp) return -1;
s->data = temp;
s->capacity = new_cap;
}
s->data[s->size++] = value;
return 0;
}
int stack_pop(Stack *s) {
if (s->size == 0) return 0;
return s->data[--s->size];
}
int stack_peek(Stack *s) {
if (s->size == 0) return 0;
return s->data[s->size - 1];
}
int stack_is_empty(Stack *s) {
return s->size == 0;
}
void example_stack(void) {
printf("=== Example 12: Stack Using Dynamic Array ===\n\n");
Stack *s = stack_create();
if (!s) return;
/* Demonstrate stack operations */
printf("Pushing: 10, 20, 30, 40, 50\n");
stack_push(s, 10);
stack_push(s, 20);
stack_push(s, 30);
stack_push(s, 40);
stack_push(s, 50);
printf("Top element (peek): %d\n", stack_peek(s));
printf("\nPopping all elements: ");
while (!stack_is_empty(s)) {
printf("%d ", stack_pop(s));
}
printf("\n\n");
stack_destroy(s);
}
/* ============================================================
* Example 13: Dynamic Array Sorting
* ============================================================ */
int compare_ints(const void *a, const void *b) {
return (*(int *)a - *(int *)b);
}
void example_sorting(void) {
printf("=== Example 13: Sorting Dynamic Arrays ===\n\n");
IntVector *v = ivec_create();
if (!v) return;
/* Add random-ish values */
int values[] = {42, 17, 89, 3, 56, 12, 91, 28, 65, 8};
int n = sizeof(values) / sizeof(values[0]);
for (int i = 0; i < n; i++) {
ivec_push(v, values[i]);
}
printf("Before sorting: ");
ivec_print(v);
/* Sort using qsort */
qsort(v->data, v->size, sizeof(int), compare_ints);
printf("After sorting: ");
ivec_print(v);
printf("\n");
ivec_destroy(v);
}
/* ============================================================
* Example 14: Dynamic 3D Array
* ============================================================ */
typedef struct {
int *data;
size_t depth;
size_t rows;
size_t cols;
} Array3D;
Array3D *array3d_create(size_t depth, size_t rows, size_t cols) {
Array3D *a = malloc(sizeof(Array3D));
if (!a) return NULL;
a->data = calloc(depth * rows * cols, sizeof(int));
if (!a->data) {
free(a);
return NULL;
}
a->depth = depth;
a->rows = rows;
a->cols = cols;
return a;
}
void array3d_destroy(Array3D *a) {
if (a) {
free(a->data);
free(a);
}
}
int array3d_get(Array3D *a, size_t z, size_t y, size_t x) {
return a->data[z * a->rows * a->cols + y * a->cols + x];
}
void array3d_set(Array3D *a, size_t z, size_t y, size_t x, int val) {
a->data[z * a->rows * a->cols + y * a->cols + x] = val;
}
void example_3d_array(void) {
printf("=== Example 14: Dynamic 3D Array ===\n\n");
Array3D *cube = array3d_create(2, 3, 4); /* 2x3x4 cube */
if (!cube) return;
/* Fill with values based on position */
int val = 0;
for (size_t z = 0; z < cube->depth; z++) {
for (size_t y = 0; y < cube->rows; y++) {
for (size_t x = 0; x < cube->cols; x++) {
array3d_set(cube, z, y, x, val++);
}
}
}
/* Print each layer */
for (size_t z = 0; z < cube->depth; z++) {
printf("Layer %zu:\n", z);
for (size_t y = 0; y < cube->rows; y++) {
printf(" ");
for (size_t x = 0; x < cube->cols; x++) {
printf("%3d ", array3d_get(cube, z, y, x));
}
printf("\n");
}
printf("\n");
}
array3d_destroy(cube);
}
/* ============================================================
* Example 15: Shrink-to-Fit and Memory Optimization
* ============================================================ */
typedef struct {
int *data;
size_t size;
size_t capacity;
} OptVector;
OptVector *optvec_create(size_t initial_cap) {
OptVector *v = malloc(sizeof(OptVector));
if (!v) return NULL;
v->data = malloc(initial_cap * sizeof(int));
if (!v->data) {
free(v);
return NULL;
}
v->size = 0;
v->capacity = initial_cap;
return v;
}
void optvec_destroy(OptVector *v) {
if (v) {
free(v->data);
free(v);
}
}
void optvec_push(OptVector *v, int value) {
if (v->size >= v->capacity) {
v->capacity *= 2;
v->data = realloc(v->data, v->capacity * sizeof(int));
}
v->data[v->size++] = value;
}
void optvec_pop(OptVector *v) {
if (v->size > 0) v->size--;
}
/* Shrink capacity to match size */
void optvec_shrink_to_fit(OptVector *v) {
if (v->size < v->capacity) {
size_t new_cap = v->size > 0 ? v->size : 1;
int *temp = realloc(v->data, new_cap * sizeof(int));
if (temp) {
v->data = temp;
v->capacity = new_cap;
}
}
}
/* Reserve specific capacity */
void optvec_reserve(OptVector *v, size_t min_cap) {
if (min_cap > v->capacity) {
int *temp = realloc(v->data, min_cap * sizeof(int));
if (temp) {
v->data = temp;
v->capacity = min_cap;
}
}
}
void example_memory_optimization(void) {
printf("=== Example 15: Memory Optimization ===\n\n");
OptVector *v = optvec_create(4);
if (!v) return;
/* Add many elements */
printf("Adding 100 elements...\n");
for (int i = 0; i < 100; i++) {
optvec_push(v, i);
}
printf("Size: %zu, Capacity: %zu\n", v->size, v->capacity);
/* Remove most elements */
printf("\nRemoving 90 elements...\n");
for (int i = 0; i < 90; i++) {
optvec_pop(v);
}
printf("Size: %zu, Capacity: %zu (wasted space!)\n", v->size, v->capacity);
/* Shrink to fit */
printf("\nShrinking to fit...\n");
optvec_shrink_to_fit(v);
printf("Size: %zu, Capacity: %zu (optimized!)\n", v->size, v->capacity);
/* Pre-reserve for known size */
printf("\nReserving for 50 elements...\n");
optvec_reserve(v, 50);
printf("Size: %zu, Capacity: %zu\n", v->size, v->capacity);
printf("\n");
optvec_destroy(v);
}
/* ============================================================
* Main Function
* ============================================================ */
int main(void) {
printf("\n");
printf("╔══════════════════════════════════════════════════════════╗\n");
printf("║ Dynamic Arrays in C - Examples ║\n");
printf("╚══════════════════════════════════════════════════════════╝\n\n");
example_basic_dynamic_array();
example_2d_array_pointers();
example_contiguous_2d_array();
example_int_vector();
example_unified_2d_array();
example_jagged_array();
example_insert_remove();
example_string_array();
example_growth_strategies();
example_bit_array();
example_circular_buffer();
example_stack();
example_sorting();
example_3d_array();
example_memory_optimization();
printf("╔══════════════════════════════════════════════════════════╗\n");
printf("║ All examples complete! ║\n");
printf("╚══════════════════════════════════════════════════════════╝\n\n");
return 0;
}