Q:

Как пользоваться полиморфизмом, но без классов с помощью языка С

Кто что слышал? Нужна инфа, заранее благодерен.

A:

Ну вот, например :)
#include <stdio.h>

typedef struct _foo {

    union {
        char c;
        int i;
    } data;

    void (*print)(struct _foo *);

} foo;

static void print_char(foo *bar)
{
    printf( "data.char: %c\n", bar->data.c );
}

static void print_int(foo *bar)
{
    printf( "data.int : %d\n", bar->data.i );
}

int main(void)
{
    foo int_foo  = { .data.i = 1,   .print = print_int  };
    foo char_foo = { .data.c = 'a', .print = print_char };
    foo *foo_ptr;

    foo_ptr = &char_foo;
    foo_ptr->print(foo_ptr);

    foo_ptr = &int_foo;
    foo_ptr->print(foo_ptr);

    return 0;
}

A:

Рискну дать свои записи из комментариев, как некий обобщенный ответ на вопрос.
Дело в том, что понятие полиморфизм - несколько более широкое понятие, нежели просто вызов виртуальных функциий в С++.  
Следует ознакомиться с самим понятием "полиморфизм". Википедия, конечно не претендует на академичность, но все же полезно почитать.
К примеру т.н. Ad hoc полиморфизм - это просто перегрузка функций. Полиморфизм подтипов - это совсем другое дело.  
Т.е. насколько я могу понять, если это экзаменационный вопрос, то он требует хотя бы какого-то знания теории типов и хорошее владение языком С.  
Мне кажется, что вам следует разобрать конкретные виды полиморфизма и попытаться реализовать каждый вид, используя относительно низкоуровневый язык. Это вполне возможно, но придется потрудиться.

