Tutorial
Variable Parameterlisten
| von  MOD | Seite 4 von 4 | 
Wichtige Hinweise
Bis einschließlich der Version 0.21.1 des Compilers gibt es einen Fehler der auftritt, wenn der erste Parameter der Funktion ein (U)Byte oder (U)Short ist. Diese Datentypen nehmen weniger als 4 Byte im Speicher ein. Durch den Fehler ergab sich ein Versatz der Adressen, da statt der wahren Größe immer 4 Byte angenommen wurden.
So führt folgender Code bis zur besagten Version zu falschen Ergebnissen:
Sub PrintInt Cdecl (anzahl As Byte, ...)
    Dim As Any Ptr argument = va_first()
    For a As Integer = 1 To anzahl
        Print va_arg(argument, Integer)
        argument = va_next(argument, Integer)
    Next
End Sub
Dim As Integer zahl1
Dim As Integer zahl2
zahl1 = 123
zahl2 = 456
PrintInt(2, zahl1, zahl2)
Sleep
Gerade beim Umgang mit Strings oder UDTs kann es durch diesen Fehler auch zu Abstürzen kommen.
Um den Fehler zu umgehen, muss dafür gesorgt werden, dass der erste Parameter 4 Byte lang ist. Man kann also schlicht Integer verwenden oder aber den Parameter  ByRef übergeben. Das bewirkt, dass intern eine Adresse übergeben wird und nicht der Wert. Adressen sind immer 4 Byte-Werte, da FreeBASIC ein 32bit-Compiler ist, was wieder zur richtigen Anzahl an Bytes führt. Die Lösung könnte also so aussehen:
ByRef übergeben. Das bewirkt, dass intern eine Adresse übergeben wird und nicht der Wert. Adressen sind immer 4 Byte-Werte, da FreeBASIC ein 32bit-Compiler ist, was wieder zur richtigen Anzahl an Bytes führt. Die Lösung könnte also so aussehen:
Sub PrintInt Cdecl (ByRef anzahl As Byte, ...)
    Dim As Any Ptr argument = va_first()
    For a As Integer = 1 To anzahl
        Print va_arg(argument, Integer)
        argument = va_next(argument, Integer)
    Next
End Sub
Dim As Integer zahl1
Dim As Integer zahl2
zahl1 = 123
zahl2 = 456
PrintInt(2, zahl1, zahl2)
Sleep
Nicht empfehlenswert ist die folgende Methode, die ich nur als Nachweis für den Verschub aufzeige.
Sub PrintInt Cdecl (anzahl As Byte, ...)
    Dim As Any Ptr argument = va_first() + 3 ' 1 Byte + 3 Byte = 4 Byte -> der Verschub wird so wieder berichtigt
    For a As Integer = 1 To anzahl
        Print va_arg(argument, Integer)
        argument = va_next(argument, Integer)
    Next
End Sub
Dim As Integer zahl1
Dim As Integer zahl2
zahl1 = 123
zahl2 = 456
PrintInt(2, zahl1, zahl2)
Sleep
Variable Parameter und Überladung
In diesem Zusammenhang wäre auch eine Überladung der Funktionen interessant, wenn man z. B. neben einer reinen Integer-Methode auch eine spezielle für  Double oder Strings haben möchte.
Double oder Strings haben möchte.
Leider ist es momentan (Version 0.21.1) nicht möglich, einer überladenen Funktion eine variable Parameterliste zu spendieren. Dies könnte sich in Zukunft allerdings ändern.
Aus diesem Grund zeige ich hier an zwei Code-Beispielen auf, wie das zukünftig aussehen könnte. Gezeigt wird eine normale Funktionsvariante und eine objektorientiere Lösung.
Declare Function add Cdecl OverLoad (anzahl As Integer, ...) As String
Declare Function add Cdecl (anzahl As String, ...) As String
Function add Cdecl (anzahl As Integer, ...) As String
    Dim As String ergebnis
    Dim As Any Ptr argument = va_first()
    For i As Integer = 1 To anzahl
        ergebnis += *va_arg(argument, ZString Ptr)
        argument = va_next(argument, ZString Ptr)
    Next
    Return ergebnis
End Function
Function add Cdecl (anzahl  As String, ...) As String
    Dim As String ergebnis
    Dim As Any Ptr argument = va_first()
    For i As Integer = 1 To ValInt(anzahl)
        ergebnis += *va_arg(argument, ZString Ptr)
        argument = va_next(argument, ZString Ptr)
    Next
    Return ergebnis
End Function
Print add(2, "Hallo ", "Welt!")
Print add("2", "Hallo ", "Welt!")
Sleep
Type myType
        Declare Function add Cdecl (anzahl As Integer, ...) As String
        Declare Function add Cdecl (anzahl As String, ...) As String
        dummy As Integer
End Type
Function myType.add Cdecl (anzahl As Integer, ...) As String
    Dim As String ret
    Dim As Any Ptr argument = va_first()
    For i As Integer = 1 To anzahl
        ergebnis += *va_arg(argument, ZString Ptr)
        argument = va_next(argument, ZString Ptr)
    Next
    Return ergebnis
End Function
Function myType.add Cdecl (anzahl As String, ...) As String
    Dim As String ergebnis
    Dim As Any Ptr argument = va_first()
    For i As Integer = 1 To ValInt(anzahl)
        ergebnis += *va_arg(argument, ZString Ptr)
        argument = va_next(argument, ZString Ptr)
    Next
    Return ergebnis
End Function
Dim As myType test
Print test.add(2, "Hallo ", "Welt!")
Print test.add("2", "Hallo ", "Welt!")
SleepWie erwähnt, diese Codes sind momentan nicht lauffähig.
| Zusätzliche Informationen und Funktionen | |||||||
|---|---|---|---|---|---|---|---|
| 
 
 | |||||||

 Wer ist online?
 Wer ist online? Buchempfehlung
 Buchempfehlung
 FreeBASIC-Chat
 FreeBASIC-Chat
 FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!
			FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us! Gehe zu Seite
 Gehe zu Seite   Bearbeiten
 Bearbeiten Versionen
 Versionen