'Versteckte' variadische Funktionen

02/10/2012 - 23:47 von Rainer Weikusat | Report spam
Ich stehe hier zZt vor dem Problem, dass eine Unterroutine zum Senden
einer Nachricht diese entweder in einem oder zwei Teilen uebergeben
bekommen soll. Der vollstaendige Prototyp ist

int etwas(struct griff *,
void const *puffer0, uint32_t laenge0,
void const *puffer1, uint32_t laenge1)

Aus technischen Gruenden (UDP-Datagram) sind die Laengen <0xffff. Die momentane Loesung sieht so aus, dass ich die Unterroutine
(via Funktionzeiger deklariert als int (*)()) fuer den ersten Fall mit
drei Argumenten aufrufe und fuer den zweiten mit fuenf. Wenn das der
Fall ist, wird das hoechstwertige Bit im ersten Laengenargument
gesetzt und der Code der jeweiligen Unterroutinen benutzt entweder nur
die ersten drei Argumente oder alle (und maskiert das Flaggen-Bit aus
bevor der entsprechende Wert an die naechste Funktion weitergegeben
wird). Wenigstens auf X86_64 funktioniert das einwandfrei und es
sollte das eigentlich auch in allen anderen Faellen tun in denen
'uebliche' Argumentuebergabe-Konventionen benutzt werden (dh alle
Parameter werden unabhaenging voneinander uebergeben). Allerdings
halte ich das augrund von 6.5.2.2|6 ("If the number of arguments does
not equal the number of parameters, the behaviour is undefined") fuer
Code mit undefiniertem Verhalten.

?
 

Lesen sie die antworten

#1 Stefan Reuther
03/10/2012 - 09:25 | Warnen spam
Rainer Weikusat wrote:
int etwas(struct griff *,
void const *puffer0, uint32_t laenge0,
void const *puffer1, uint32_t laenge1)

Aus technischen Gruenden (UDP-Datagram) sind die Laengen <> 0xffff. Die momentane Loesung sieht so aus, dass ich die Unterroutine
(via Funktionzeiger deklariert als int (*)()) fuer den ersten Fall mit
drei Argumenten aufrufe und fuer den zweiten mit fuenf.



Wenn "du" die aufrufst, was spricht denn dagegen, die anderen beiden
Argumente auch mit reinzustopfen?

Wenigstens auf X86_64 funktioniert das einwandfrei und es
sollte das eigentlich auch in allen anderen Faellen tun in denen
'uebliche' Argumentuebergabe-Konventionen benutzt werden (dh alle
Parameter werden unabhaenging voneinander uebergeben). Allerdings
halte ich das augrund von 6.5.2.2|6 ("If the number of arguments does
not equal the number of parameters, the behaviour is undefined") fuer
Code mit undefiniertem Verhalten.



"undefiniertes Verhalten" schließt bekanntermaßen den Fall mit ein, dass
es genau so funktioniert, wie der Programmierer im konkreten Fall erwartet.

Wenn ich die Bedingungen für Funktionsaufrufe korrekt überblicke, darf
ein C-Compiler Funktionen, die kein "..." im Prototyp enthalten, mit dem
aufrufen, was man gemeinhin "pascal calling conventions" nennt, und was
auf gewissen Plattformen effizienter ist als "C calling conventions".
Dann werden die Argumente "andersrum" übergeben und es funktioniert
nicht. Vor Urzeiten hatte ich mal einen Spielzeugcompiler in den Hànden,
der das tat. Aktuelle Compiler tun's wohl nicht.

Außerdem bleibt natürlich zu beachten, dass 'uint32_t' größer als 'int'
sein kann, folglich beim Aufruf ohne Prototyp brav gecastet werden muss :-)


Stefan

Ähnliche fragen