Original geschrieben von Thomas Engelke
Wie stelle ich mir das auf Systemebene vor? Wie liegen denn die Parameter auf dem Stack? Wie kann dann der Aufgerufene zwischen einem 0-Pointer als Wert und dem vereinbarten Endewert unterscheiden? Der "Trick", wie ich ihn von getch() kenne (Rückgabewert als signed int definieren, damit ich ein -1 mitbekommen kann, welcher kein gültiger Wert ist), kann ja hier nicht funktionieren, da doch eh mit 32bit-Werten gearbeitet wird und es imho keinen Wert gibt, der nicht auch ein valider Parameterwert sein könnte.
Erstmal ein paar Beispiel Funktionen.
Eine Funktion,die eine beliebige Anzahl Strings ausgibt, abgeschlossen durch einen Null Pointer
Code:
void printChars(char *arg, ...)
{
char *str;
va_list ap;
va_start(ap,arg);
puts(arg);
str = va_arg(ap,char*);
while(str)
{
puts(str);
str = va_arg(ap,char*);
}
va_end(ap);
}
...
printChars("Hello","World","!",(char*)0);
Eine Funktion, die eine beliebige Anzahl ints ausgibt, abgeschlossen durch eine -1
Code:
void printInts(int arg, ...)
{
int num;
va_list ap;
va_start(ap,arg);
printf("%d\n",arg);
num = va_arg(ap,int);
while(num != -1)
{
printf("%d\n",num);
num = va_arg(ap,int);
}
va_end(ap);
}
...
printInts(1,2,3,4,5,-1);
So, va_start initialisiert ap, dazu wird der letzte benannte Parameter der Funktion benötigt.
arg hat eine Adresse, und alle Parameter, die noch folgen werden liegen geordnet im Speicherbereich dahinter.
Das va_arg Makro setzt jetzt immer den Zeiger (ap) weiter.Wieviel?Na,das wird durch den 2.Parameter bestimmt, der ein Datentyp ist (int,char*,...), die Größe gibt an,wieweit der Zeiger inkrementiert werden muß.
Und damit hangeln wir uns durch den Speicher.
Lesezeichen