Я присутствовал на техническом интервью несколько дней назад, и меня спросили, Как делает компилятор C implments функция с Переменным количеством аргументов? Как это передает стеку?
Кто-либо знает, или может explian это?
Спасибо, Dan
Он реализует их с помощью макроса va_, например va_start . Именно то, что делают эти макросы, определяется реализацией - другими словами, это будет варьироваться от архитектуры ЦП к архитектуре и от компилятора к компилятору. Но они должны сыграть злую шутку со стеком вызовов C. Как правило, это будет включать в себя взятие адреса последнего указанного параметра в качестве основы, а затем доступ к параметрам с переменным числом аргументов путем выполнения арифметических операций с указателями на этой основе.
Посмотрите на va_start, va_arg и va_end. Вот тонна информации по этому поводу.
Насколько вам грустно, что вы получили этот вопрос на техническом собеседовании, я Предположим, что правильным ответом будет:
Вызывающий будет помещать явные параметры в стек, количество переменных параметров и сам параметр переменных. Затем код целевой функции будет отвечать за вывод всех параметров на основе переданного счетчика и адреса стека.
И добавьте несколько идей, почему помещать эти параметры в отдельный массив неудобно.
Насколько мне известно, с C ...
вызывающая функция помещает аргументы в стек в порядке справа налево.
вызывающая сторона отвечает за удаление аргументов из стека после выполнения вызываемой функции. Вероятно, это связано с тем, что вызывающий гарантированно знает, сколько аргументов он помещает в стек, в то время как вызываемая функция может ошибиться.
P.S .: Соглашения о вызовах обычно зависят от реализации . То, что я только что описал, известно как соглашение о вызовах "cdecl". Сравните это с соглашением о вызовах, обычно известным как "stdcall", где вызываемая функция отвечает за удаление своих аргументов из стека. По этой причине он не поддерживает списки аргументов переменной длины.
P.P.S .: Как прокомментировал пользователь nategoose, я не упомянул, как на самом деле используются списки переменных аргументов . См., Например, документация POSIX для заголовка
для получения дополнительной информации.