va_first

Returns a pointer to the first argument in a variable argument list

Syntax
   pointer_variable = va_first()

Description
   The va_first function provides an untyped pointer value that points to 
   the first variable argument passed to a function.

   Not supported when using -gen gcc.  Use Cva_List variadic argument list 
   type for cross platform compatibility.

Example
   Function average cdecl(count As Integer, ... ) As Double
      Dim arg As Any Ptr
      Dim sum As Double = 0
      Dim i As Integer
      
      arg = va_first()

      For i = 1 To count
         sum += va_arg(arg, Double)
         arg = va_next(arg, Double)
      Next
      
      Return sum / count
   End Function

   Print average(4, 3.4,5.0,3.2,4.1)  '' all passed variable arguments must be of type double
   Print average(2, 65.2,454.65481)   '' all passed variable arguments must be of type double
   Sleep

The output would look like:

   3.925
   259.927405

   '' Example of a simple custom printf
   Sub myprintf cdecl(ByRef formatstring As String, ...)
      '' Get the pointer to the first var-arg
      Dim As Any Ptr arg = va_first()

      '' For each char in format string...
      Dim As UByte Ptr p = StrPtr(formatstring)
      Dim As Integer todo = Len(formatstring)
      While (todo > 0)
         Dim As Integer char = *p
         p += 1
         todo -= 1

         '' Is it a format char?
         If (char = Asc("%")) Then
            If (todo = 0) Then
               '' % at the end
               Print "%";
               Exit While
            End If

            '' The next char should tell the type
            char = *p
            p += 1
            todo -= 1

            '' Print var-arg, depending on the type
            Select Case char
            '' integer?
            Case Asc("i")
               Print Str(va_arg(arg, Integer));
               '' Note, different from C: va_next() must be
               '' used as va_arg() won't update the pointer.
               arg = va_next(arg, Integer)

            '' long integer? (64-bit)
            Case Asc("l")
               Print Str(va_arg(arg, LongInt));
               arg = va_next(arg, LongInt)

            '' single or double?
            '' Note: because the C ABI, all singles passed on
            '' var-args are converted to doubles.
            Case Asc( "f" ), Asc( "d" )
               Print Str(va_arg(arg, Double));
               arg = va_next(arg, Double)

            '' string?
            Case Asc("s")
               '' Strings are passed byval, so the length is unknown
               Print *va_arg(arg, ZString Ptr);
               arg = va_next(arg, ZString Ptr)

            End Select

         '' Ordinary char, just print as-is
         Else
            Print Chr( char );
         End If
      Wend
   End Sub

      Dim As String s = "bar"

      myprintf(!"integer=%i, longint=%l single=%f, double=%d, string=%s, string=%s\n", _
             1, 1ll Shl 32, 2.2, 3.3, "foo", s)

      Sleep

Dialect Differences
   * Not available in the -lang qb dialect unless referenced with the 
     alias __Va_first.

Differences from QB
   * New to FreeBASIC

See also
   * ... (Ellipsis)
   * va_arg
   * va_next

