На 32-битной x86 с Cdecl вызова конвенции, параметры передаются в стек:
^ 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)
Вы можете реализовать va_list
как указатель. va_start
может передать адрес переданного ему аргумента и добавить размер этого аргумента для перехода к следующему аргументу. va_arg
может получить доступ к указателю и подвести его к следующему аргументу. va_copy
может просто скопировать значение указателя. va_end
ничего не нужно делать.
Если, с другой стороны, вы не используете cdecl (возможно, вы используете fastcall), вы не 32-битный, вы не x86, это не сработает; вам может понадобиться гасить регистры, а не только значения указателя. И даже это еще не гарантировано, потому что вы полагаетесь на неопределенное поведение; как пример только одной потенциальной проблемы, вложение может испортить все. И вот почему заголовочный файл просто typedef
s это для компилятора, встроенного в реализацию этого в C, безнадежно, вам нужна поддержка компилятора. И даже не заставляйте меня начинать с внедрения setjmp
и longjmp
...
Почему бы не просто заглянуть в ** заголовок **, предоставленный вашим предпочтительным компилятором? Обратите внимание, что это специфично для реализации. Любой всеобъемлющий ответ был бы слишком широким. Пожалуйста, будьте более конкретными. – Olaf
@Olaf Я искал исходный код gcc, clang и glibc в течение 2 часов, и я не мог найти тот, который даже удаленно выглядит как реализация. –
Пожалуйста, внимательно прочитайте первое предложение моего комментария. Собственно, прочитайте весь комментарий. – Olaf