#include #include struct int_list { int value; struct int_list* next; }; void int_list_insert( struct int_list** ls, int x ) { struct int_list* node = malloc(sizeof(struct int_list)); node->value = x; node->next = *ls; *ls = node; } int int_list_head( const struct int_list* ls ) { return ls->value; } // all code must be duplicated for every generic instantiation struct string_list { const char* value; struct string_list* next; }; void string_list_insert( struct string_list** ls, const char* x ) { struct string_list* node = malloc(sizeof(struct string_list)); node->value = x; node->next = *ls; *ls = node; } const char* string_list_head( const struct string_list* ls ) { return ls->value; } // use is efficient and idiomatic int main() { struct int_list* il = NULL; int_list_insert( &il, 42 ); printf("%d\n", int_list_head(il)); struct string_list* sl = NULL; string_list_insert( &sl, "hello" ); printf("%s\n", string_list_head(sl) ); }