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.
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 typedef
s 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
…