Technically, how do variadic functions work? How does printf work?

前端 未结 2 1412
自闭症患者
自闭症患者 2020-12-02 09:21

I know I can use va_arg to write my own variadic functions, but how do variadic functions work under the hood, i.e. on the assembly instruction level?

E

2条回答
  •  旧巷少年郎
    2020-12-02 09:58

    Variadic functions are defined by the standard, with very few explicit restrictions. Here is an example, lifted from cplusplus.com.

    /* va_start example */
    #include       /* printf */
    #include      /* va_list, va_start, va_arg, va_end */
    
    void PrintFloats (int n, ...)
    {
      int i;
      double val;
      printf ("Printing floats:");
      va_list vl;
      va_start(vl,n);
      for (i=0;i

    The assumptions are roughly as follows.

    1. There must be (at least one) first, fixed, named argument. The ... actually does nothing, except tell the compiler to do the right thing.
    2. The fixed argument(s) provide information about how many variadic arguments there are, by an unspecified mechanism.
    3. From the fixed argument it is possible for the va_start macro to return an object that allows arguments to be retrieved. The type is va_list.
    4. From the va_list object it is possible for va_arg to iterate over each variadic argument, and coerce its value it into a compatible type.
    5. Something weird might have happened in va_start so va_end makes things right again.

    In the most usual stack-based situation, the va_list is merely a pointer to the arguments sitting on the stack, and va_arg increments the pointer, casts it and dereferences it to a value. Then va_start initialises that pointer by some simple arithmetic (and inside knowledge) and va_end does nothing. There is no strange assembly language, just some inside knowledge of where things lie on the stack. Read the macros in the standard headers to find out what that is.

    Some compilers (MSVC) will require a specific calling sequence, whereby the caller will release the stack rather than the callee.

    Functions like printf work exactly like this. The fixed argument is a format string, which allows the number of arguments to be calculated.

    Functions like vsprintf pass the va_list object as a normal argument type.

    If you need more or lower level detail, please add to the question.

提交回复
热议问题