Variadic arguments heißt aber nicht 'alles'
« | 23 Jun 2019 | »Heute ist mir mal wieder ein lustiger Fehler in Zusammenhang mit variadic arguments in C passiert.
Denn da es in C keine Templates und Funktionsüberladungen gibt, sind
varargs
die einzige Möglichkeit mit einer Funktionssignatur beliebige
Parameter auszuführen.
Tja, und dann hatte ich plötzlich einen Fehler im GCC, obwohl der MSVC alles kompilieren konnte.
Um es nicht zu spannend zu machen:
Der Fehler trat bei einem va_arg(arglist, char);
auf.
Anfangs war ich verwirrt, las dann aber nach, warum GCC hier bockt … und dann fiel es mir auch wieder ein:
Datentypen kleiner als
int
müssen beiva_arg
s auf einenint
beim Lesen vergrößert werden.
Das macht auch Sinn, denn int
wird in C gerne mit der
Standardausrichtung
(standard alignment) belegt.
Und wenn man sich die va_arg
Funktion mal ansieht, ist sie auf X86 als
Pointeraddition implementiert, wo der Argumentpointer immer um die Größe
des gewünschten Typen verschoben wird.
Und nachdem auf dem Stack Alignment-Regeln gelten, würde ein
va_arg(arglist, char)
den Pointer nur um ein Byte verschieben, und
schon hätten wir die Alignmentregeln gebrochen.
Mit int
verschieben sich Pointer in geordneten Bahnen.
Das heißt also, dass
1char c = va_arg(arglist, char);
falsch ist und durch
1char c = (char)va_arg(arglist, int);
ersetzt werden muss.
Nun gut. Aber warum haben wir unter Windows kein Problem während der GCC unter Linux bockt?
Naja, MSVC versucht Programmierfehler abzufangen und korrigiert den falschen Datentypen automatisch, was der GCC (völlig korrekt) nicht tut.
Microsoft’s Versuche hier etwas zu verbessern sind aber eigentlich ein
Schuss ins Knie, wie auch andere Beispiele zeigen.
Denn wann immer ein Compiler vom Standard abweicht entsteht nicht portierbarer
Code und dann beginnt Jahre später die Debatte, dass man nicht auf einen
neueren Compiler wechseln darf, weil der dann dem Standard entspricht
aber die Programme darauf nicht mehr funktionieren.
Wie auch immer … ich habe wieder etwas Wissen aufgefrischt und der GATE Code läuft nun auch auf GCC und Linux wieder so wie er soll.
Alles in allem war es dann doch noch ein schöner Tag.