Search code examples
cheader-files

How to implement stdarg in C


For curiosity, I'm looking to write minimal replacements for some of the functions in the standard C library. So far, I have finished printf(), strlen(), strcpy(), memcpy(), memset(), etc... but when I try to use the printf function, I don't know how to implement stdarg.h! What is a way that I could do that?

Does it use macros or actual functions?

I am using gcc OR clang on 32-bit x86, if it helps to make this any easier to answer.


Solution

  • On 32-bit x86 with the cdecl calling convention, parameters are passed on the stack:

    ^ higher addresses (lower on the stack)
    |
    | caller local variables
    | ...
    | argument 3
    | argument 2
    | argument 1
    | return address
    | saved EBP (usually)
    | callee local variables
    |
    v lower addresses (higher on the stack)
    

    You can implement va_list as a pointer. va_start can take the address of the argument passed to it and add the size of that argument to move to the next argument. va_arg can access the pointer and bump it to the next argument. va_copy can just copy the pointer value. va_end doesn’t need to do anything.

    If, on the other hand, you’re not using cdecl (maybe you’re using fastcall), you’re not 32-bit, you’re not x86, this won’t work; you might need to muck with registers rather than just pointer values. And even still it’s not guaranteed to work, since you’re relying on undefined behavior; as as example of only one potential problem, inlining could ruin everything. And that’s why the header file just typedefs it to a compiler built-in—implementing this in C is hopeless, you need compiler support. And don’t even get me started on implementing setjmp and longjmp