Dein Lehrer will wahrscheinlich auf void* hinaus.
Ich halte diese Aufgabenstellung aber zu schwierig für Anfänger.
Man kann auch Makros mit generischen Aktionen kombinieren:
/* eigener Testtyp (neben double und string s.u.) */
typedef struct {
char name[20];
int alter;
char geschlecht;
} Person;
/* Aktionen für jeden Typ */
void f_double(double*d) { printf("%f\n",*d); }
void f_string(char*d) { puts(d); }
void f_struct(Person*d) { printf("%s %d %c\n",d->name,d->alter,d->geschlecht); }
/* anonymer Stackelement-Typ */
typedef struct {
void (*f)();
void *d;
} Eintrag;
/* Aktionen für den Stack */
enum{PUSH,POP,PRINTALL};
/* unser Stack-Typ */
typedef struct{
Eintrag (*work)();
int i;
Eintrag eintrag[100];
} Stack;
#define CALL(x) x.f(x.d)
#define doublePUSH(s,p) s.work(&s,PUSH,p,f_double)
#define stringPUSH(s,p) s.work(&s,PUSH,p,f_string)
#define structPUSH(s,p) s.work(&s,PUSH,p,f_struct)
#define DOStack(s,e) s.work(&s,e)
/* alle Stackoperationen in einer Funktion zusammengefasst */
Eintrag work(Stack *this,int e,void*p,void(*f)())
{
switch(e){
case POP: return this->eintrag[--this->i];
case PUSH: { Eintrag e={f,p}; this->eintrag[this->i++]=e;break; }
case PRINTALL: { int i=this->i; while(i--) CALL(this->eintrag[i]);}
}
}
int main()
{
int i;
Eintrag eintrag;
/* Testdaten mit 3 unterschiedlichen Typen bereitstellen */
double d[]={1,2,3};
char *s[]={"s1","s2","s3"};
Person p[]={{"schmidt",47,'m'},{"meier",11,'w'},{"lehmann",12,'m'}};
/* unser Stack-Objekt */
Stack stack={work};
/* Testdaten mit ihren unterschiedlichen Typen in EINEN Stack packen (eigentliche Aufgabe) */
for(i=0;i<3;++i)
doublePUSH(stack,&d[i]),stringPUSH(stack,s[i]),structPUSH(stack,&p[i]);
/* Kontrollausgabe: gesamter Stackinhalt */
DOStack(stack,PRINTALL);
/* Stack einzeln wieder abräumen und dabei jedes Element nochmal kontrollausgeben */
for(i=0;i<9;++i)
eintrag=DOStack(stack,POP),CALL(eintrag);
return 0;
}
http://ideone.com/oGH0d1