Buchempfehlung
Mikrocomputertechnik mit Controllern der Atmel AVR-RISC-Familie
Mikrocomputertechnik mit Controllern der Atmel AVR-RISC-Familie
Umfassend, aber leicht verständlich führt dieses Buch in die Programmierung von ATMEL AVR Mikrocontrollern ein. [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

Referenz - VA_FIRST

Referenz-Navigation

 

Syntax: VA_FIRST
Typ: Funktion
Kategorie: Speicher

VA_FIRST gibt einen Pointer auf den ersten Parameter einer variablen Parameterliste zurück.

Unter FreeBASIC ist es möglich, Prozeduren zu erstellen, die keine festgelegte Parameterliste besitzen. Diesen Prozeduren darf eine beliebig lange Parameterliste übergeben werden, und die Parameter dürfen von jedem Datentyp sein. Eine solche Liste wird variable Parameterliste genannt. Um dies zu ermöglichen, verwendet man bei BefehlsreferenzeintragDECLARE und im Prozedurheader folgende Syntax:

DECLARE {SUB|FUNCTION} (<'normaleParameter'>, ...)

'normaleParameter' ist dabei eine normale Parameterliste, wie bei BefehlsreferenzeintragDECLARE erklärt. Das '...' leitet die variable Parameterliste ein.

Bei dieser Form der Übergabe geht aber die Information verloren, um welche Datentypen es sich in der variablen Liste handelt bzw. wie viele Parameter übergeben wurden. Daher werden oft sogenannte Format-Strings in der normalen Parameterliste übergeben, in denen beschrieben wird, welche Parameter übergeben wurden. Dieser Format-String darf jedes beliebige Format besitzen, da der Programmierer die Parameterübergabe komplett selbst übernimmt. Der String muss ihm lediglich die Informationen liefern, die er braucht, um die Werte aus der variablen Parameterliste herauszulesen.

BefehlsreferenzeintragVA_ARG wird dazu benutzt, um den Wert eines Parameters zu ermitteln. BefehlsreferenzeintragVA_NEXT aktualisiert den von VA_FIRST zurückgegebenen Pointer, sodass er auf das nächste Argument der variablen Parameterliste zeigt.

Beispiel (aus dem examples-Ordner des FreeBASIC-Verzeichnisses):

' Beispiel für variable Parameter
Declare Sub myPrintf cdecl (byRef FormatierString As String, ...)

Dim s as String = "bar"

myPrintf "Integer=%i, LongInt=%l, Single=%f, Double=%d, String=%s, String=%s", _
         1, 1LL shl 32, 2.2, 3.3, "foo", s
Sleep

Sub myPrintf cdecl (byRef FormatierString As String, ...)
  Dim As Integer i, c
  Dim As String s
  Dim As Any Ptr Arg = va_first  ' Pointer zum ersten variablen Argument holen
  Dim As ZString Ptr p

  p = StrPtr(FormatierString)
  i = Len(FormatierString)
  Do While i>0  ' Für jedes Zeichen in FormatierString..
    c = *p
    p += 1
    i -= 1
    ' Ist es ein Formatierzeichen?
    If Chr(c) = "%" Then  ' Typ holen
      c = *p
      p += 1
      i -= 1
      ' variables Argument ausgeben, abhängig vom Typ
      Select Case Chr(c)
        Case "i"  ' Integer?
          s = s & va_arg(Arg, Integer)
          Arg = va_next(Arg, Integer)
          ' Anders als in C muss va_next() benutzt werden, da
          ' va_arg() die Pointer nicht aktualisiert
        Case "l"  ' LongInteger? (64-bit)
          s = s & va_arg(Arg, LongInt)
          Arg = va_next(Arg, LongInt)
        Case "f", "d"
          ' Single oder Double? (Beachte: wegen der C-ABI werden alle Singles, die
          ' übergeben wurden, in Doubles konvertiert)
          s = s & va_arg(Arg, Double)
          Arg = va_next(Arg, Double)
        Case "s"  ' String?
          ' Strings werden byVal übergeben, also ist ihre Länge unbekannt
          s = s & *va_arg(Arg, ZString Ptr)
          Arg = va_next(Arg, ZString Ptr)
      End Select
    Else  ' normales Zeichen, einfach ausgeben..
      s = s & Chr( c )
    End If
  Loop
  Print s;
End Sub

Beispiel 2 (verkürzte Variante):

Sub myPrint Cdecl (FormatierString As String, ...)
  Dim As Any Ptr argument = va_first
  Dim As Integer i
  Dim As ZString Ptr p

  For i = 1 To Len(FormatierString)

    Select Case Mid(FormatierString, i, 1)
      Case "i"
        Print "Integer:  " & va_arg(argument, Integer)
        argument = va_next(argument, Integer)
      Case "l"
        Print "LongInt:  " & va_arg(argument, LongInt)
        argument = va_next(argument, LongInt)
      Case "f", "d"
        Print "Double:   " & va_arg(argument, Double)
        argument = va_next(argument, Double)
      Case "s"
        Print "String:   " & *va_arg(argument, ZString Ptr)
        argument = va_next(argument, ZString Ptr)
    End Select
  Next
End Sub

'###############################################################

Dim s As String = "String2"

myPrint( "ilfdss", 1, 4294967296, 1.2, 3.4, "String1", s )
Sleep

Hinweis:
Eine BefehlsreferenzeintragSUB/BefehlsreferenzeintragFUNCTION, die eine variable Parameterliste verwendet, muss zwingend mit BefehlsreferenzeintragCDECL deklariert werden. Ansonsten meldet der Compiler einen Fehler.

Unterschiede zu QB: neu in FreeBASIC

Plattformbedingte Unterschiede:
VA_FIRST wird nicht unterstützt, wenn mit der BefehlsreferenzeintragCompileroption '-gen gcc' compiliert wird. Für plattformübergreifende Kompatibilität verwenden Sie die BefehlsreferenzeintragFunktionen zum Umgang mit CVA_LIST.

Unterschiede unter den FB-Dialektformen:
In der Dialektform Befehlsreferenzeintrag-lang qb steht VA_FIRST nicht zur Verfügung und kann nur über __VA_FIRST aufgerufen werden.

Siehe auch:
BefehlsreferenzeintragVA_ARG, BefehlsreferenzeintragVA_NEXT, BefehlsreferenzeintragCVA_START, BefehlsreferenzeintragCVA_COPY, BefehlsreferenzeintragCVA_ARG, BefehlsreferenzeintragCVA_END, BefehlsreferenzeintragDECLARE, BefehlsreferenzeintragSUB, BefehlsreferenzeintragFUNCTION, BefehlsreferenzeintragCDECL, BefehlsreferenzeintragDatentypen, Befehlsreferenzeintrag... (Auslassung[Ellipsis]), BefehlsreferenzeintragProzeduren


Zusätzliche Informationen und Funktionen
  • Der Referenzeintrag wurde am 17.07.2007 von Redakteurnemored angelegt.
  • Die aktuellste Version wurde am 18.08.2020 von Redakteurnemored gespeichert.
  Versionen Versionen