Generics in C
Our first program will demonstrate the concept of generics in C. Here’s the full source code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// Generic function to find the index of an element in an array
#define SlicesIndex(type, arr, size, value) ({ \
int index = -1; \
for (int i = 0; i < size; i++) { \
if (arr[i] == value) { \
index = i; \
break; \
} \
} \
index; \
})
// Generic linked list structure
#define DEFINE_LIST(T) \
typedef struct Node_##T { \
T value; \
struct Node_##T* next; \
} Node_##T; \
\
typedef struct { \
Node_##T* head; \
Node_##T* tail; \
} List_##T; \
\
void Push_##T(List_##T* list, T value) { \
Node_##T* new_node = malloc(sizeof(Node_##T)); \
new_node->value = value; \
new_node->next = NULL; \
if (list->tail == NULL) { \
list->head = list->tail = new_node; \
} else { \
list->tail->next = new_node; \
list->tail = new_node; \
} \
} \
\
T* AllElements_##T(List_##T* list) { \
int size = 0; \
Node_##T* current = list->head; \
while (current != NULL) { \
size++; \
current = current->next; \
} \
T* elements = malloc(size * sizeof(T)); \
current = list->head; \
for (int i = 0; i < size; i++) { \
elements[i] = current->value; \
current = current->next; \
} \
return elements; \
}
// Define List for int type
DEFINE_LIST(int)
int main() {
char* s[] = {"foo", "bar", "zoo"};
int size = sizeof(s) / sizeof(s[0]);
// Using the generic SlicesIndex function
int index = SlicesIndex(char*, s, size, "zoo");
printf("index of zoo: %d\n", index);
// Using the generic List
List_int list = {NULL, NULL};
Push_int(&list, 10);
Push_int(&list, 13);
Push_int(&list, 23);
int* elements = AllElements_int(&list);
printf("list: ");
for (int i = 0; i < 3; i++) {
printf("%d ", elements[i]);
}
printf("\n");
free(elements);
return 0;
}
In this C implementation, we’ve used preprocessor macros to simulate generics. The SlicesIndex
macro creates a generic function to find the index of an element in an array. The DEFINE_LIST
macro defines a generic linked list structure and its associated functions.
To compile and run the program:
$ gcc -o generics generics.c
$ ./generics
index of zoo: 2
list: 10 13 23
This example demonstrates how to implement generic-like functionality in C using macros. While C doesn’t have built-in support for generics like some modern languages, this approach allows for type-agnostic code reuse.
Note that this implementation has limitations and doesn’t provide true type safety at compile-time. In practice, more robust solutions might involve code generation or careful use of void pointers, depending on the specific requirements of the project.