Variadic arguments heißt aber nicht 'alles'

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 bei va_args auf einen int 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 geordneteren Bahnen.

Das heißt also, dass

char c = va_arg(arglist, char);

falsch ist und durch

char 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?

Hmm, 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.


Wenn sich eine triviale Erkenntnis mit Dummheit in der Interpretation paart, dann gibt es in der Regel Kollateralschäden in der Anwendung.
frei zitiert nach A. Van der Bellen
... also dann paaren wir mal eine komplexe Erkenntnis mit Klugheit in der Interpretation!